带键的集合是指使用键(key)来访问值(value)的数据结构。JavaScript 提供了多种带键的集合类型,每种都有其特点和适用场景。
// 创建对象
const obj1 = {}; // 空对象
const obj2 = new Object(); // 构造函数
const obj3 = Object.create(null); // 没有原型的对象
// 字面量语法
const person = {
name: "张三",
age: 25,
"first-name": "张", // 包含特殊字符的键名
1: "数字键", // 数字键会被转换为字符串
[Symbol("id")]: "symbol键", // Symbol作为键
};
// 访问属性
console.log(person.name); // "张三"
console.log(person["age"]); // 25(括号表示法)
console.log(person["first-name"]); // "张"(必须使用括号表示法)
// 添加/修改属性
person.city = "北京";
person["age"] = 26;
// 删除属性
delete person.city;
// 检查属性是否存在
console.log("name" in person); // true
console.log(person.hasOwnProperty("name")); // true
console.log("toString" in person); // true(继承自原型)
console.log(person.hasOwnProperty("toString")); // false
// 遍历属性
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key, person[key]);
}
}
// 获取所有键、值、键值对
console.log(Object.keys(person)); // ["name", "age", "first-name", "1"]
console.log(Object.values(person)); // ["张三", 26, "张", "数字键"]
console.log(Object.entries(person)); // [["name", "张三"], ["age", 26], ...]
// 获取属性描述符
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// {value: "张三", writable: true, enumerable: true, configurable: true}
// 属性描述符
const obj = {};
// 定义属性(完整控制)
Object.defineProperty(obj, "readonlyProp", {
value: "不能修改",
writable: false, // 不可写
enumerable: true, // 可枚举
configurable: false, // 不可配置(不可删除、不可修改描述符)
});
Object.defineProperty(obj, "hiddenProp", {
value: "隐藏属性",
enumerable: false, // 不可枚举(不会出现在for...in中)
});
// 尝试修改只读属性
obj.readonlyProp = "新值";
console.log(obj.readonlyProp); // "不能修改"(修改失败)
// 尝试删除不可配置属性
delete obj.readonlyProp;
console.log(obj.readonlyProp); // "不能修改"(删除失败)
// 检查枚举性
console.log(Object.keys(obj)); // ["readonlyProp"](不包含hiddenProp)
console.log(Object.getOwnPropertyNames(obj)); // ["readonlyProp", "hiddenProp"]
// 定义多个属性
Object.defineProperties(obj, {
prop1: {
value: "value1",
writable: true,
},
prop2: {
value: "value2",
enumerable: false,
},
});
// 密封对象(不能添加/删除属性,现有属性可修改)
const sealedObj = { x: 1 };
Object.seal(sealedObj);
sealedObj.x = 2; // 允许
sealedObj.y = 3; // 失败(严格模式报错)
delete sealedObj.x; // 失败
console.log(Object.isSealed(sealedObj)); // true
// 冻结对象(完全不可变)
const frozenObj = { x: 1 };
Object.freeze(frozenObj);
frozenObj.x = 2; // 失败
frozenObj.y = 3; // 失败
delete frozenObj.x; // 失败
console.log(Object.isFrozen(frozenObj)); // true
// 创建Map
const map1 = new Map(); // 空Map
const map2 = new Map([
["name", "Alice"],
["age", 25],
[1, "数字键"],
[{}, "对象键"], // 对象作为键
[Symbol("id"), "Symbol键"], // Symbol作为键
]);
// 基本操作
const map = new Map();
// 添加/设置值
map.set("name", "Bob");
map.set("age", 30);
map.set("age", 31); // 更新已存在的键
map.set({ id: 1 }, "对象作为键"); // 对象可以作为键
// 获取值
console.log(map.get("name")); // "Bob"
console.log(map.get("gender")); // undefined(不存在的键)
// 检查键是否存在
console.log(map.has("name")); // true
console.log(map.has("gender")); // false
// 删除键值对
map.delete("age");
console.log(map.has("age")); // false
// 清空Map
map.clear();
console.log(map.size); // 0
// 获取大小
map.set("a", 1).set("b", 2).set("c", 3);
console.log(map.size); // 3
// 键可以是任意值
const keyObj = { x: 1 };
const keyFunc = function () {};
const keyArray = [1, 2, 3];
map.set(keyObj, "对象值");
map.set(keyFunc, "函数值");
map.set(keyArray, "数组值");
console.log(map.get(keyObj)); // "对象值"
console.log(map.get(keyFunc)); // "函数值"
console.log(map.get(keyArray)); // "数组值"
// 注意:只有同一个引用才能获取值
console.log(map.get({ x: 1 })); // undefined(不同的对象)
console.log(map.get([1, 2, 3])); // undefined(不同的数组)
const map = new Map([
["name", "Charlie"],
["age", 28],
["city", "Shanghai"],
["job", "Developer"],
]);
// 1. keys() - 遍历键
for (const key of map.keys()) {
console.log("键:", key);
}
// 2. values() - 遍历值
for (const value of map.values()) {
console.log("值:", value);
}
// 3. entries() - 遍历键值对
for (const [key, value] of map.entries()) {
console.log(`${key}: ${value}`);
}
// 4. forEach() - 回调遍历
map.forEach((value, key, map) => {
console.log(`${key} = ${value}`);
});
// 5. for...of 直接遍历(默认使用entries)
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// 6. 使用展开运算符转换
console.log([...map.keys()]); // ['name', 'age', 'city', 'job']
console.log([...map.values()]); // ['Charlie', 28, 'Shanghai', 'Developer']
console.log([...map.entries()]); // [['name', 'Charlie'], ['age', 28], ...]
console.log([...map]); // 同上(Map本身是可迭代的)
// 7. Map转数组的实用方法
const entriesArray = Array.from(map);
console.log(entriesArray);
// 8. Map转对象
const obj = Object.fromEntries(map);
console.log(obj); // {name: 'Charlie', age: 28, city: 'Shanghai', job: 'Developer'}
// 9. 对象转Map
const newMap = new Map(Object.entries(obj));
console.log(newMap);
// 1. 链式调用
const map = new Map();
map.set("a", 1).set("b", 2).set("c", 3).set("d", 4);
// 2. 使用复杂对象作为键
class User {
constructor(id, name) {
this.id = id;
this.name = name;
}
// 为了能在Map中正确识别,重写toString
toString() {
return `User#${this.id}`;
}
// 为了比较相等,重写valueOf
valueOf() {
return this.id;
}
}
const user1 = new User(1, "Alice");
const user2 = new User(2, "Bob");
const user3 = new User(1, "Alice Clone"); // 相同ID
const userMap = new Map();
userMap.set(user1, "User 1 data");
userMap.set(user2, "User 2 data");
console.log(userMap.get(user1)); // "User 1 data"
console.log(userMap.get(user3)); // undefined(虽然是相同ID,但是不同对象)
// 3. 使用函数作为键
function createKey(prefix, id) {
return `${prefix}:${id}`;
}
const funcMap = new Map();
funcMap.set(createKey("user", 1), { name: "Alice" });
funcMap.set(createKey("user", 2), { name: "Bob" });
// 4. Map的相等性比较
const map1 = new Map([["a", 1]]);
const map2 = new Map([["a", 1]]);
console.log(map1 === map2); // false(不同的实例)
// 5. 嵌套Map
const nestedMap = new Map([
[
"config",
new Map([
["timeout", 5000],
["retry", 3],
[
"headers",
new Map([
["Content-Type", "application/json"],
["Authorization", "Bearer token"],
]),
],
]),
],
["cache", new Map()],
]);
console.log(nestedMap.get("config").get("headers").get("Content-Type")); // "application/json"
// 6. Map与数组的转换
function mapToArray(map) {
return Array.from(map, ([key, value]) => ({
key,
value,
type: typeof key,
}));
}
function arrayToMap(array, keySelector, valueSelector) {
return new Map(array.map(item => [keySelector(item), valueSelector(item)]));
}
// 使用示例
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const userMap2 = arrayToMap(
users,
user => user.id,
user => user
);
// WeakMap只能使用对象作为键
let obj1 = { id: 1 };
let obj2 = { id: 2 };
let obj3 = { id: 3 };
const weakMap = new WeakMap();
// 设置键值对
weakMap.set(obj1, "data for obj1");
weakMap.set(obj2, "data for obj2");
weakMap.set(obj3, { nested: "data" });
// 获取值
console.log(weakMap.get(obj1)); // "data for obj1"
console.log(weakMap.get(obj2)); // "data for obj2"
console.log(weakMap.get({ id: 1 })); // undefined(必须是同一个对象引用)
// 检查键是否存在
console.log(weakMap.has(obj1)); // true
// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // false
// WeakMap的特点
console.log(weakMap.size); // undefined(WeakMap没有size属性)
// console.log(weakMap.keys()); // 错误:WeakMap没有keys()方法
// console.log(weakMap.values()); // 错误:WeakMap没有values()方法
// console.log(weakMap.entries()); // 错误:WeakMap没有entries()方法
// console.log([...weakMap]); // 错误:WeakMap不可迭代
// 键是弱引用
obj2 = null; // 当obj2被垃圾回收时,WeakMap中的对应条目会自动被移除
// 验证垃圾回收(需要手动触发或等待)
setTimeout(() => {
console.log(weakMap.has(obj3)); // true(obj3仍然存在)
}, 1000);
// 场景1:私有属性存储
const privateData = new WeakMap();
class Person {
constructor(name, age) {
// 将实例作为键,私有数据作为值
privateData.set(this, {
name,
age,
createdAt: new Date(),
_secret: "私有数据",
});
}
// 公共方法访问私有数据
getName() {
return privateData.get(this).name;
}
getAge() {
return privateData.get(this).age;
}
setAge(newAge) {
const data = privateData.get(this);
if (data) {
data.age = newAge;
}
}
// 静态方法无法访问,因为无法获取this
}
const alice = new Person("Alice", 25);
const bob = new Person("Bob", 30);
console.log(alice.getName()); // "Alice"
console.log(bob.getName()); // "Bob"
// 无法直接访问私有数据
console.log(alice._secret); // undefined
console.log(privateData.get(alice)); // {name: 'Alice', age: 25, ...}
// 场景2:缓存计算结果
const cache = new WeakMap();
function expensiveOperation(obj) {
if (cache.has(obj)) {
console.log("从缓存获取结果");
return cache.get(obj);
}
console.log("执行计算并缓存结果");
const result = {
computed: obj.value * 2,
timestamp: new Date(),
};
cache.set(obj, result);
return result;
}
const data1 = { value: 10 };
const data2 = { value: 20 };
console.log(expensiveOperation(data1)); // 计算并缓存
console.log(expensiveOperation(data1)); // 从缓存获取
console.log(expensiveOperation(data2)); // 计算并缓存
// 场景3:DOM元素关联数据
const domData = new WeakMap();
function attachData(element, data) {
domData.set(element, data);
}
function getData(element) {
return domData.get(element);
}
function handleClick(event) {
const element = event.target;
const data = getData(element);
if (data) {
data.clickCount = (data.clickCount || 0) + 1;
data.lastClick = new Date();
console.log(`点击次数: ${data.clickCount}`);
}
}
// 创建按钮并关联数据
const button = document.createElement("button");
button.textContent = "点击我";
attachData(button, {
id: "btn-1",
clickCount: 0,
created: new Date(),
});
button.addEventListener("click", handleClick);
// 场景4:对象元数据
const metadata = new WeakMap();
function addMetadata(obj, key, value) {
if (!metadata.has(obj)) {
metadata.set(obj, new Map());
}
metadata.get(obj).set(key, value);
}
function getMetadata(obj, key) {
const objMetadata = metadata.get(obj);
return objMetadata ? objMetadata.get(key) : undefined;
}
const product = { name: "Laptop", price: 1000 };
addMetadata(product, "source", "API");
addMetadata(product, "fetchedAt", new Date());
console.log(getMetadata(product, "source")); // "API"
console.log(getMetadata(product, "fetchedAt")); // Date对象
// 实现观察者模式
class Observable {
constructor() {
this._observers = new WeakMap();
}
addObserver(observer, callback) {
if (!this._observers.has(this)) {
this._observers.set(this, new WeakMap());
}
this._observers.get(this).set(observer, callback);
}
removeObserver(observer) {
const observerMap = this._observers.get(this);
if (observerMap) {
observerMap.delete(observer);
}
}
notify(data) {
const observerMap = this._observers.get(this);
if (observerMap) {
for (const [observer, callback] of observerMap) {
callback.call(observer, data);
}
}
}
}
// 实现撤销/重做功能
class StateManager {
constructor() {
this._states = new WeakMap();
}
saveState(obj, state) {
if (!this._states.has(obj)) {
this._states.set(obj, []);
}
this._states.get(obj).push({
state: JSON.parse(JSON.stringify(state)), // 深拷贝
timestamp: new Date(),
});
}
getLastState(obj) {
const states = this._states.get(obj);
return states ? states[states.length - 1] : null;
}
undo(obj) {
const states = this._states.get(obj);
if (states && states.length > 1) {
states.pop();
return this.getLastState(obj);
}
return null;
}
}
// 实现依赖跟踪
class DependencyTracker {
constructor() {
this._dependencies = new WeakMap();
this._dependents = new WeakMap();
}
addDependency(dependent, dependency) {
// 记录dependent依赖于哪些dependency
if (!this._dependencies.has(dependent)) {
this._dependencies.set(dependent, new Set());
}
this._dependencies.get(dependent).add(dependency);
// 记录dependency被哪些dependent依赖
if (!this._dependents.has(dependency)) {
this._dependents.set(dependency, new Set());
}
this._dependents.get(dependency).add(dependent);
}
getDependents(dependency) {
return this._dependents.get(dependency) || new Set();
}
removeDependent(dependent) {
const dependencies = this._dependencies.get(dependent);
if (dependencies) {
for (const dep of dependencies) {
const dependents = this._dependents.get(dep);
if (dependents) {
dependents.delete(dependent);
}
}
this._dependencies.delete(dependent);
}
}
}
// Set是值的集合,每个值只能出现一次
const set1 = new Set(); // 空Set
const set2 = new Set([1, 2, 3, 2, 1]); // 自动去重 [1, 2, 3]
const set3 = new Set("hello"); // Set(4) {"h", "e", "l", "o"}
// 基本操作
const set = new Set();
// 添加值
set.add(1);
set.add(2);
set.add(2); // 重复值不会被添加
set.add("hello");
set.add({ a: 1 }); // 对象可以添加
set.add([1, 2, 3]); // 数组也可以添加
// 检查值是否存在
console.log(set.has(1)); // true
console.log(set.has(3)); // false
// 删除值
set.delete(2);
console.log(set.has(2)); // false
// 清空Set
set.clear();
console.log(set.size); // 0
// 获取大小
set.add("a").add("b").add("c");
console.log(set.size); // 3
// 遍历
for (const value of set) {
console.log(value);
}
set.forEach((value, valueAgain, set) => {
console.log(value);
});
// Set转数组
const array = [...set];
console.log(array); // ['a', 'b', 'c']
// 实用操作
function unique(arr) {
return [...new Set(arr)];
}
console.log(unique([1, 2, 2, 3, 3, 3])); // [1, 2, 3]
// 并集
function union(setA, setB) {
return new Set([...setA, ...setB]);
}
// 交集
function intersection(setA, setB) {
return new Set([...setA].filter(x => setB.has(x)));
}
// 差集 (A - B)
function difference(setA, setB) {
return new Set([...setA].filter(x => !setB.has(x)));
}
// 对称差集
function symmetricDifference(setA, setB) {
return union(difference(setA, setB), difference(setB, setA));
}
// 子集判断
function isSubset(setA, setB) {
return [...setA].every(x => setB.has(x));
}
// 超集判断
function isSuperset(setA, setB) {
return [...setB].every(x => setA.has(x));
}
// 使用示例
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);
console.log(union(setA, setB)); // Set(6) {1, 2, 3, 4, 5, 6}
console.log(intersection(setA, setB)); // Set(2) {3, 4}
console.log(difference(setA, setB)); // Set(2) {1, 2}
console.log(symmetricDifference(setA, setB)); // Set(4) {1, 2, 5, 6}
console.log(isSubset(new Set([1, 2]), setA)); // true
console.log(isSuperset(setA, new Set([1, 2]))); // true
// WeakSet只能存储对象
let obj1 = { id: 1 };
let obj2 = { id: 2 };
let obj3 = { id: 3 };
const weakSet = new WeakSet();
// 添加对象
weakSet.add(obj1);
weakSet.add(obj2);
weakSet.add(obj3);
// 检查对象是否存在
console.log(weakSet.has(obj1)); // true
console.log(weakSet.has({ id: 1 })); // false(必须是同一个对象)
// 删除对象
weakSet.delete(obj1);
console.log(weakSet.has(obj1)); // false
// WeakSet的特点
console.log(weakSet.size); // undefined(没有size属性)
// console.log([...weakSet]); // 错误:WeakSet不可迭代
// 应用场景1:标记已处理对象
const processed = new WeakSet();
function processObject(obj) {
if (processed.has(obj)) {
console.log("对象已处理,跳过");
return;
}
console.log("处理对象:", obj);
// 处理逻辑...
processed.add(obj);
}
// 应用场景2:确保对象只能被添加一次
class UniqueRegistry {
constructor() {
this._registry = new WeakSet();
}
register(obj) {
if (this._registry.has(obj)) {
throw new Error("对象已注册");
}
this._registry.add(obj);
}
isRegistered(obj) {
return this._registry.has(obj);
}
unregister(obj) {
this._registry.delete(obj);
}
}
// 应用场景3:DOM元素管理
const trackedElements = new WeakSet();
function trackElement(element) {
trackedElements.add(element);
element.classList.add("tracked");
}
function isElementTracked(element) {
return trackedElements.has(element);
}
// 创建一些DOM元素
const div1 = document.createElement("div");
const div2 = document.createElement("div");
trackElement(div1);
console.log(isElementTracked(div1)); // true
console.log(isElementTracked(div2)); // false
// 性能测试函数
function benchmark(name, operation, iterations = 100000) {
const start = performance.now();
for (let i = 0; i < iterations; i++) {
operation(i);
}
const end = performance.now();
const duration = end - start;
console.log(`${name}: ${duration.toFixed(2)}ms (${(duration / iterations).toFixed(4)}ms/op)`);
return duration;
}
// 准备测试数据
const size = 10000;
const testData = [];
for (let i = 0; i < size; i++) {
testData.push({
key: `key${i}`,
value: `value${i}`,
});
}
// 对象性能测试
const obj = {};
testData.forEach(({ key, value }) => {
obj[key] = value;
});
console.log("=== 查找性能 ===");
benchmark("Object属性访问", i => {
const key = `key${i % size}`;
return obj[key];
});
// Map性能测试
const map = new Map();
testData.forEach(({ key, value }) => {
map.set(key, value);
});
benchmark("Map.get", i => {
const key = `key${i % size}`;
return map.get(key);
});
// WeakMap性能测试
const weakMap = new WeakMap();
const refs = [];
testData.forEach(({ key, value }, index) => {
const objKey = { key };
refs.push(objKey); // 保持引用,防止被垃圾回收
weakMap.set(objKey, value);
});
benchmark("WeakMap.get", i => {
const index = i % size;
return weakMap.get(refs[index]);
});
console.log("\n=== 插入性能 ===");
benchmark("Object赋值", i => {
obj[`newKey${i}`] = `newValue${i}`;
});
benchmark("Map.set", i => {
map.set(`newKey${i}`, `newValue${i}`);
});
console.log("\n=== 删除性能 ===");
benchmark("Object delete", i => {
delete obj[`key${i % size}`];
});
benchmark("Map.delete", i => {
map.delete(`key${i % size}`);
});
console.log("\n=== 迭代性能 ===");
benchmark("Object.keys forEach", () => {
Object.keys(obj).forEach(key => {
const value = obj[key];
});
});
benchmark("Map.forEach", () => {
map.forEach((value, key) => {});
});
// 选择指南函数
function suggestCollectionType(useCase) {
const suggestions = {
// 使用对象的情况
simpleKeyValue: {
message: "使用普通对象 Object",
reason: "键是字符串或Symbol,不需要复杂功能",
example: `const config = {
host: 'localhost',
port: 8080,
timeout: 5000
};`,
},
// 使用Map的情况
complexKeys: {
message: "使用 Map",
reason: "键可能是对象、函数等非字符串类型",
example: `const cache = new Map();
const user = { id: 1 };
cache.set(user, userData);`,
},
needSize: {
message: "使用 Map",
reason: "需要方便的获取元素数量(obj需要Object.keys(obj).length)",
example: `const map = new Map([['a', 1], ['b', 2]]);
console.log(map.size); // 2`,
},
frequentAddDelete: {
message: "使用 Map",
reason: "频繁添加和删除键值对",
example: `const session = new Map();
// 频繁更新会话数据
session.set('token', newToken);
session.delete('oldToken');`,
},
preserveOrder: {
message: "使用 Map",
reason: "需要保持插入顺序(ES6+对象也保持顺序,但Map更可靠)",
example: `const orderedMap = new Map();
orderedMap.set('first', 1);
orderedMap.set('second', 2);
// 遍历时保证顺序`,
},
// 使用WeakMap的情况
privateData: {
message: "使用 WeakMap",
reason: "需要存储对象的私有数据,避免内存泄漏",
example: `const privateData = new WeakMap();
class MyClass {
constructor() {
privateData.set(this, { privateProp: 'secret' });
}
}`,
},
cacheWithObjectKeys: {
message: "使用 WeakMap",
reason: "缓存计算结果,键是对象,希望对象被回收时缓存也自动清除",
example: `const cache = new WeakMap();
function compute(obj) {
if (cache.has(obj)) return cache.get(obj);
const result = expensiveCompute(obj);
cache.set(obj, result);
return result;
}`,
},
// 使用Set的情况
uniqueValues: {
message: "使用 Set",
reason: "只需要存储唯一值,不需要键值对",
example: `const uniqueTags = new Set();
tags.forEach(tag => uniqueTags.add(tag));`,
},
setOperations: {
message: "使用 Set",
reason: "需要进行集合运算(并集、交集、差集等)",
example: `const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);
const union = new Set([...setA, ...setB]);`,
},
// 使用WeakSet的情况
trackObjects: {
message: "使用 WeakSet",
reason: "只需要标记对象是否存在,希望对象被回收时自动移除",
example: `const processed = new WeakSet();
function process(obj) {
if (processed.has(obj)) return;
processed.add(obj);
// 处理逻辑
}`,
},
};
return (
suggestions[useCase] || {
message: "使用普通对象 Object",
reason: "默认选择,适用于大多数简单场景",
}
);
}
// 使用示例
console.log(suggestCollectionType("complexKeys"));
console.log(suggestCollectionType("privateData"));
console.log(suggestCollectionType("uniqueValues"));
// 集合转换工具类
class CollectionConverter {
// Object ↔ Map
static objectToMap(obj) {
return new Map(Object.entries(obj));
}
static mapToObject(map) {
return Object.fromEntries(map);
}
// Array ↔ Set
static arrayToSet(arr) {
return new Set(arr);
}
static setToArray(set) {
return [...set];
}
// Map ↔ Array
static mapToArray(map, transformer = ([key, value]) => ({ key, value })) {
return Array.from(map, transformer);
}
static arrayToMap(arr, keySelector, valueSelector) {
return new Map(
arr.map(item => [keySelector(item), valueSelector ? valueSelector(item) : item])
);
}
// 深拷贝集合
static deepCloneMap(original) {
const cloned = new Map();
for (const [key, value] of original) {
if (value instanceof Map) {
cloned.set(key, this.deepCloneMap(value));
} else if (value instanceof Set) {
cloned.set(key, this.deepCloneSet(value));
} else if (value instanceof Object && !Array.isArray(value)) {
cloned.set(key, JSON.parse(JSON.stringify(value)));
} else {
cloned.set(key, value);
}
}
return cloned;
}
static deepCloneSet(original) {
const cloned = new Set();
for (const value of original) {
if (value instanceof Map) {
cloned.add(this.deepCloneMap(value));
} else if (value instanceof Set) {
cloned.add(this.deepCloneSet(value));
} else if (value instanceof Object) {
cloned.add(JSON.parse(JSON.stringify(value)));
} else {
cloned.add(value);
}
}
return cloned;
}
// 集合合并
static mergeMaps(...maps) {
const result = new Map();
for (const map of maps) {
for (const [key, value] of map) {
result.set(key, value);
}
}
return result;
}
static mergeSets(...sets) {
const result = new Set();
for (const set of sets) {
for (const value of set) {
result.add(value);
}
}
return result;
}
// 集合比较
static mapsEqual(map1, map2) {
if (map1.size !== map2.size) return false;
for (const [key, value] of map1) {
if (!map2.has(key) || map2.get(key) !== value) {
return false;
}
}
return true;
}
static setsEqual(set1, set2) {
if (set1.size !== set2.size) return false;
for (const value of set1) {
if (!set2.has(value)) {
return false;
}
}
return true;
}
}
// 使用示例
const obj = { a: 1, b: 2, c: 3 };
const map = CollectionConverter.objectToMap(obj);
console.log(map); // Map(3) {"a" => 1, "b" => 2, "c" => 3}
const set = new Set([1, 2, 3, 4]);
const arr = CollectionConverter.setToArray(set);
console.log(arr); // [1, 2, 3, 4]
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const userMap = CollectionConverter.arrayToMap(
users,
user => user.id,
user => user.name
);
console.log(userMap); // Map(2) {1 => "Alice", 2 => "Bob"}
记住选择原则:简单的键值对用 Object,复杂的键或需要顺序用 Map,私有数据或缓存用 WeakMap,唯一值集合用 Set,对象标记用 WeakSet。