// 1. 数组字面量(推荐)
const arr1 = [1, 2, 3];
const arr2 = ["a", "b", "c"];
const arr3 = [1, "hello", true, null, undefined];
const arr4 = []; // 空数组
// 2. Array 构造函数
const arr5 = new Array(); // 空数组 []
const arr6 = new Array(5); // 长度为5的空数组 [empty × 5]
const arr7 = new Array(1, 2, 3); // [1, 2, 3]
// 3. Array.of() - 解决构造函数歧义
console.log(Array.of(5)); // [5]
console.log(Array.of(1, 2, 3)); // [1, 2, 3]
// 4. Array.from() - 从类数组或可迭代对象创建
console.log(Array.from("hello")); // ['h', 'e', 'l', 'l', 'o']
console.log(Array.from([1, 2, 3], x => x * 2)); // [2, 4, 6]
// 5. 稀疏数组
const sparse = [1, , 3]; // 第二个位置是空位
console.log(sparse.length); // 3
console.log(sparse[1]); // undefined
// 6. 多维数组
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const fruits = ["apple", "banana", "orange"];
// 获取长度
console.log(fruits.length); // 3
// 访问元素
console.log(fruits[0]); // 'apple'
console.log(fruits[1]); // 'banana'
console.log(fruits[2]); // 'orange'
console.log(fruits[3]); // undefined(越界访问)
// 修改元素
fruits[0] = "grape";
console.log(fruits); // ['grape', 'banana', 'orange']
// 修改长度
fruits.length = 2;
console.log(fruits); // ['grape', 'banana'](截断)
fruits.length = 5;
console.log(fruits); // ['grape', 'banana', empty × 3]
console.log(fruits[4]); // undefined
// 清空数组
fruits.length = 0;
console.log(fruits); // []
const numbers = [1, 2, 3, 4, 5];
// 1. for 循环(最灵活)
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
// 2. for...of(推荐用于值遍历)
for (const num of numbers) {
console.log(num);
}
// 3. forEach(函数式)
numbers.forEach((num, index, array) => {
console.log(`${index}: ${num}`);
});
// 4. map(返回新数组)
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// 5. filter(过滤)
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
// 6. reduce(归约)
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
// 7. 遍历稀疏数组
const sparse = [1, , 3];
sparse.forEach((item, index) => {
console.log(index, item); // 0 1, 2 3(跳过空位)
});
for (let i = 0; i < sparse.length; i++) {
console.log(i, sparse[i]); // 0 1, 1 undefined, 2 3
}
// 添加/删除元素
const arr = [1, 2, 3];
// push - 末尾添加
arr.push(4, 5);
console.log(arr); // [1, 2, 3, 4, 5]
// pop - 末尾删除
const last = arr.pop();
console.log(last, arr); // 5, [1, 2, 3, 4]
// unshift - 开头添加
arr.unshift(0);
console.log(arr); // [0, 1, 2, 3, 4]
// shift - 开头删除
const first = arr.shift();
console.log(first, arr); // 0, [1, 2, 3, 4]
// splice - 万能修改
arr.splice(1, 2); // 从索引1开始删除2个元素
console.log(arr); // [1, 4]
arr.splice(1, 0, 2, 3); // 从索引1开始删除0个,插入2,3
console.log(arr); // [1, 2, 3, 4]
arr.splice(2, 1, "a", "b"); // 从索引2开始删除1个,插入'a','b'
console.log(arr); // [1, 2, 'a', 'b', 4]
// slice - 切片(不修改原数组)
const sliced = arr.slice(1, 3);
console.log(sliced, arr); // [2, 'a'], [1, 2, 'a', 'b', 4]
// concat - 连接(不修改原数组)
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = arr1.concat(arr2, [5, 6]);
console.log(combined); // [1, 2, 3, 4, 5, 6]
// 展开运算符(ES6+)
const spread = [...arr1, ...arr2, 5, 6];
console.log(spread); // [1, 2, 3, 4, 5, 6]
const arr = [1, 2, 3, 4, 5, 2];
// indexOf / lastIndexOf
console.log(arr.indexOf(2)); // 1(第一个)
console.log(arr.lastIndexOf(2)); // 5(最后一个)
console.log(arr.indexOf(10)); // -1(未找到)
// includes(ES2016+)
console.log(arr.includes(3)); // true
console.log(arr.includes(3, 3)); // false(从索引3开始找)
// find / findIndex(ES6+)
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
console.log(users.find(user => user.name === "Bob")); // {id: 2, name: 'Bob'}
console.log(users.findIndex(user => user.id === 2)); // 1
// findLast / findLastIndex(ES2023+)
console.log(arr.findLast(x => x === 2)); // 2
console.log(arr.findLastIndex(x => x === 2)); // 5
// some / every
console.log(arr.some(x => x > 3)); // true(至少有一个满足)
console.log(arr.every(x => x > 0)); // true(所有都满足)
// 排序
const numbers = [3, 1, 4, 1, 5, 9, 2];
// 默认排序(按字符串Unicode码点)
numbers.sort();
console.log(numbers); // [1, 1, 2, 3, 4, 5, 9]
// 自定义排序
numbers.sort((a, b) => a - b); // 升序
console.log(numbers); // [1, 1, 2, 3, 4, 5, 9]
numbers.sort((a, b) => b - a); // 降序
console.log(numbers); // [9, 5, 4, 3, 2, 1, 1]
// 对象数组排序
const items = [
{ name: "Apple", price: 5 },
{ name: "Banana", price: 2 },
{ name: "Orange", price: 3 },
];
items.sort((a, b) => a.price - b.price);
console.log(items);
// 反转
const reversed = numbers.reverse();
console.log(reversed);
// 转换字符串
const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
console.log(arr.join()); // "1,2,3"
console.log(arr.join("-")); // "1-2-3"
console.log(arr.join("")); // "123"
// 扁平化(ES2019+)
const nested = [1, [2, [3, [4]]]];
console.log(nested.flat()); // [1, 2, [3, [4]]]
console.log(nested.flat(2)); // [1, 2, 3, [4]]
console.log(nested.flat(Infinity)); // [1, 2, 3, 4]
// flatMap(ES2019+)
const phrases = ["hello world", "good morning"];
const words = phrases.flatMap(phrase => phrase.split(" "));
console.log(words); // ['hello', 'world', 'good', 'morning']
// Int8Array:8位有符号整数(-128 ~ 127)
const int8 = new Int8Array([1, 2, 3]);
console.log(int8); // Int8Array(3) [1, 2, 3]
// Uint8Array:8位无符号整数(0 ~ 255)
const uint8 = new Uint8Array([255, 256, 257]);
console.log(uint8); // Uint8Array(3) [255, 0, 1](溢出处理)
// Uint8ClampedArray:8位无符号整数(0 ~ 255,钳制值)
const clamped = new Uint8ClampedArray([255, 256, 257]);
console.log(clamped); // Uint8ClampedArray(3) [255, 255, 255]
// Int16Array:16位有符号整数
const int16 = new Int16Array([32767, 32768]);
console.log(int16); // Int16Array(2) [32767, -32768](溢出)
// Uint16Array:16位无符号整数
const uint16 = new Uint16Array([65535, 65536]);
console.log(uint16); // Uint16Array(2) [65535, 0]
// Int32Array:32位有符号整数
const int32 = new Int32Array([2147483647, 2147483648]);
console.log(int32); // Int32Array(2) [2147483647, -2147483648]
// Uint32Array:32位无符号整数
const uint32 = new Uint32Array([4294967295, 4294967296]);
console.log(uint32); // Uint32Array(2) [4294967295, 0]
// Float32Array:32位浮点数
const float32 = new Float32Array([1.1, 2.2, 3.3]);
console.log(float32); // Float32Array(3) [1.100000023841858, 2.200000047683716, 3.299999952316284]
// Float64Array:64位浮点数(等同于普通JavaScript数字)
const float64 = new Float64Array([1.1, 2.2, 3.3]);
console.log(float64); // Float64Array(3) [1.1, 2.2, 3.3]
// BigInt64Array:64位有符号大整数
const bigInt64 = new BigInt64Array([1n, 2n, 3n]);
console.log(bigInt64); // BigInt64Array(3) [1n, 2n, 3n]
// BigUint64Array:64位无符号大整数
const bigUint64 = new BigUint64Array([1n, 2n, 3n]);
console.log(bigUint64); // BigUint64Array(3) [1n, 2n, 3n]
// 1. 创建指定长度的类型化数组
const typed1 = new Int8Array(4); // 创建长度为4的数组
console.log(typed1); // Int8Array(4) [0, 0, 0, 0]
// 2. 从普通数组创建
const typed2 = new Int16Array([1, 2, 3, 4]);
// 3. 从ArrayBuffer创建
const buffer = new ArrayBuffer(16); // 16字节
const typed3 = new Int32Array(buffer);
console.log(typed3.length); // 4(16字节 ÷ 4字节/元素 = 4个元素)
// 4. 从另一个类型化数组创建
const source = new Int8Array([1, 2, 3, 4]);
const typed4 = new Int16Array(source);
console.log(typed4); // Int16Array(4) [1, 2, 3, 4]
// 5. 使用from()和of()
const typed5 = Int8Array.from([1, 2, 3]);
const typed6 = Int8Array.of(1, 2, 3);
// 访问和修改
const arr = new Int8Array([10, 20, 30, 40]);
console.log(arr[0]); // 10
console.log(arr.length); // 4
arr[0] = 100;
console.log(arr[0]); // 100
// 越界赋值(有符号类型会溢出)
arr[0] = 300; // 300 > 127
console.log(arr[0]); // 44(溢出计算:300 - 256 = 44)
// 遍历
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
for (const value of arr) {
console.log(value);
}
arr.forEach((value, index) => {
console.log(index, value);
});
const arr = new Int8Array([1, 2, 3, 4]);
// 属性
console.log(arr.length); // 4(元素个数)
console.log(arr.byteLength); // 4(字节长度)
console.log(arr.byteOffset); // 0(在ArrayBuffer中的偏移量)
console.log(arr.buffer); // ArrayBuffer对象
console.log(arr.BYTES_PER_ELEMENT); // 1(每个元素占用的字节数)
// 类数组方法(大部分普通数组方法都可用)
const doubled = arr.map(x => x * 2);
console.log(doubled); // Int8Array(4) [2, 4, 6, 8]
const filtered = arr.filter(x => x > 2);
console.log(filtered); // Int8Array(2) [3, 4]
const sum = arr.reduce((acc, val) => acc + val, 0);
console.log(sum); // 10
// set() - 复制数据
const dest = new Int8Array(8);
dest.set(arr, 2); // 从索引2开始复制
console.log(dest); // Int8Array(8) [0, 0, 1, 2, 3, 4, 0, 0]
// subarray() - 创建视图(不复制数据)
const sub = arr.subarray(1, 3); // 包含1,不包含3
console.log(sub); // Int8Array(2) [2, 3]
sub[0] = 100;
console.log(arr); // Int8Array(4) [1, 100, 3, 4](原数组也被修改)
// slice() - 创建副本
const copy = arr.slice(1, 3);
console.log(copy); // Int8Array(2) [100, 3]
copy[0] = 200;
console.log(arr); // Int8Array(4) [1, 100, 3, 4](原数组不变)
// 创建ArrayBuffer
const buffer = new ArrayBuffer(16);
// 创建DataView
const view = new DataView(buffer);
// 写入不同格式的数据
view.setInt8(0, 127); // 在偏移0写入8位有符号整数
view.setUint8(1, 255); // 在偏移1写入8位无符号整数
view.setInt16(2, 32767); // 在偏移2写入16位有符号整数
view.setUint16(4, 65535); // 在偏移4写入16位无符号整数
view.setFloat32(8, 3.14); // 在偏移8写入32位浮点数
view.setFloat64(12, 2.71828); // 在偏移12写入64位浮点数
// 读取数据
console.log(view.getInt8(0)); // 127
console.log(view.getUint8(1)); // 255
console.log(view.getInt16(2)); // 32767
console.log(view.getUint16(4)); // 65535
console.log(view.getFloat32(8)); // 3.140000104904175
console.log(view.getFloat64(12)); // 2.71828
// 指定字节序(littleEndian参数)
view.setInt16(6, 0x1234, true); // 小端序
console.log(view.getInt16(6, true)); // 0x1234
console.log(view.getInt16(6, false)); // 0x3412(大端序读取)
// 实用示例:解析二进制文件头
function parsePNGHeader(buffer) {
const view = new DataView(buffer);
// PNG文件头签名
const signature = [
view.getUint8(0), // 137
view.getUint8(1), // 80
view.getUint8(2), // 78
view.getUint8(3), // 71
view.getUint8(4), // 13
view.getUint8(5), // 10
view.getUint8(6), // 26
view.getUint8(7), // 10
];
// 读取IHDR块
const length = view.getUint32(8);
const chunkType = [view.getUint8(12), view.getUint8(13), view.getUint8(14), view.getUint8(15)];
const width = view.getUint32(16);
const height = view.getUint32(20);
return {
width,
height,
bitDepth: view.getUint8(24),
colorType: view.getUint8(25),
compression: view.getUint8(26),
filter: view.getUint8(27),
interlace: view.getUint8(28),
};
}
// 创建Map
const map1 = new Map();
const map2 = new Map([
["name", "Alice"],
["age", 25],
["city", "Beijing"],
]);
// 基本操作
const map = new Map();
// set() - 添加键值对
map.set("name", "Bob");
map.set("age", 30);
map.set("age", 31); // 更新值
map.set({}, "object key"); // 对象作为键
// get() - 获取值
console.log(map.get("name")); // 'Bob'
console.log(map.get("gender")); // undefined
// has() - 检查键是否存在
console.log(map.has("name")); // true
console.log(map.has("gender")); // false
// delete() - 删除键值对
map.delete("age");
console.log(map.has("age")); // false
// clear() - 清空Map
map.clear();
console.log(map.size); // 0
// size - 获取元素数量
map.set("a", 1).set("b", 2).set("c", 3);
console.log(map.size); // 3
const map = new Map([
["name", "Charlie"],
["age", 28],
["city", "Shanghai"],
]);
// 遍历键
for (const key of map.keys()) {
console.log(key); // 'name', 'age', 'city'
}
// 遍历值
for (const value of map.values()) {
console.log(value); // 'Charlie', 28, 'Shanghai'
}
// 遍历键值对
for (const [key, value] of map.entries()) {
console.log(`${key}: ${value}`);
}
// forEach遍历
map.forEach((value, key, map) => {
console.log(`${key} = ${value}`);
});
// Map转数组
console.log(Array.from(map)); // [['name', 'Charlie'], ['age', 28], ['city', 'Shanghai']]
console.log([...map]); // 同上
// Map转对象
const obj = Object.fromEntries(map);
console.log(obj); // {name: 'Charlie', age: 28, city: 'Shanghai'}
// 对象转Map
const newMap = new Map(Object.entries(obj));
console.log(newMap);
// 嵌套Map
const nestedMap = new Map([
[
"user1",
new Map([
["name", "Alice"],
["age", 25],
]),
],
[
"user2",
new Map([
["name", "Bob"],
["age", 30],
]),
],
]);
console.log(nestedMap.get("user1").get("name")); // 'Alice'
// WeakMap只能使用对象作为键
let obj1 = { id: 1 };
let obj2 = { id: 2 };
const weakMap = new WeakMap();
// 设置键值对
weakMap.set(obj1, "data for obj1");
weakMap.set(obj2, "data for obj2");
// 获取值
console.log(weakMap.get(obj1)); // 'data for obj1'
// 检查键是否存在
console.log(weakMap.has(obj1)); // true
// 删除
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // false
// WeakMap特点:键是弱引用
obj1 = null; // 垃圾回收可以回收obj1,WeakMap中的对应条目也会被自动移除
// 应用场景1:私有属性
const privateData = new WeakMap();
class User {
constructor(name, age) {
// 将实例作为键,私有数据作为值
privateData.set(this, {
name,
age,
createdAt: new Date(),
});
}
getName() {
return privateData.get(this).name;
}
getAge() {
return privateData.get(this).age;
}
// 其他公共方法...
}
// 应用场景2:缓存
const cache = new WeakMap();
function processData(obj) {
if (cache.has(obj)) {
console.log("从缓存获取");
return cache.get(obj);
}
console.log("计算并缓存");
const result = expensiveOperation(obj);
cache.set(obj, result);
return result;
}
// 应用场景3:DOM元素关联数据
const domData = new WeakMap();
const button = document.createElement("button");
domData.set(button, {
clickCount: 0,
lastClicked: null,
});
button.addEventListener("click", () => {
const data = domData.get(button);
data.clickCount++;
data.lastClicked = new Date();
console.log(`点击次数: ${data.clickCount}`);
});
// 创建Set
const set1 = new Set();
const set2 = new Set([1, 2, 3, 3, 2, 1]); // 自动去重
console.log(set2); // Set(3) {1, 2, 3}
// 基本操作
const set = new Set();
// add() - 添加值
set.add(1);
set.add(2);
set.add(2); // 重复值不会被添加
set.add("hello");
set.add({ a: 1 }); // 对象可以添加
// has() - 检查值是否存在
console.log(set.has(1)); // true
console.log(set.has(3)); // false
// delete() - 删除值
set.delete(2);
console.log(set.has(2)); // false
// clear() - 清空Set
set.clear();
console.log(set.size); // 0
// size - 获取元素数量
set.add("a").add("b").add("c");
console.log(set.size); // 3
const set = new Set(["apple", "banana", "orange"]);
// 遍历值
for (const fruit of set) {
console.log(fruit);
}
for (const fruit of set.values()) {
console.log(fruit);
}
// forEach遍历
set.forEach((value, valueAgain, set) => {
console.log(value);
});
// Set转数组
const array = Array.from(set);
console.log(array); // ['apple', 'banana', 'orange']
const array2 = [...set];
console.log(array2); // 同上
// 数组去重
const numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4]
// 字符串去重
const str = "hello world";
const uniqueChars = [...new Set(str)].join("");
console.log(uniqueChars); // 'helo wrd'
// 并集
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 new Set([...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
// WeakSet只能存储对象
let obj1 = { id: 1 };
let obj2 = { id: 2 };
const weakSet = new WeakSet();
// add() - 添加对象
weakSet.add(obj1);
weakSet.add(obj2);
// has() - 检查对象是否存在
console.log(weakSet.has(obj1)); // true
// delete() - 删除对象
weakSet.delete(obj1);
console.log(weakSet.has(obj1)); // false
// WeakSet特点:弱引用
obj1 = null; // 垃圾回收可以回收obj1
// 应用场景:标记对象
const processed = new WeakSet();
function processObject(obj) {
if (processed.has(obj)) {
console.log("对象已处理,跳过");
return;
}
console.log("处理对象");
// ...处理逻辑...
processed.add(obj);
}
// 应用场景:确保对象只能被添加一次到集合
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);
}
}
// 性能测试工具
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;
}
// 数组 vs Set 查找性能
const array = [];
const set = new Set();
// 准备数据
for (let i = 0; i < 10000; i++) {
array.push(i);
set.add(i);
}
console.log("=== 查找性能测试 ===");
benchmark("Array.includes", i => array.includes(i % 10000));
benchmark("Set.has", i => set.has(i % 10000));
console.log("\n=== 添加性能测试 ===");
const testArray = [];
const testSet = new Set();
benchmark("Array.push", i => testArray.push(i));
benchmark("Set.add", i => testSet.add(i));
console.log("\n=== 删除性能测试 ===");
benchmark("Array.splice", i => {
const index = testArray.indexOf(i);
if (index > -1) {
testArray.splice(index, 1);
}
});
benchmark("Set.delete", i => testSet.delete(i));
// Map vs Object 性能测试
const map = new Map();
const obj = {};
for (let i = 0; i < 10000; i++) {
map.set(`key${i}`, i);
obj[`key${i}`] = i;
}
console.log("\n=== Map vs Object 查找性能 ===");
benchmark("Map.get", i => map.get(`key${i % 10000}`));
benchmark("Object.property", i => obj[`key${i % 10000}`]);
console.log("\n=== 迭代性能 ===");
benchmark("Map.forEach", () => {
map.forEach((value, key) => {});
});
benchmark("Object.keys forEach", () => {
Object.keys(obj).forEach(key => {});
});
// 内存占用估算函数
function estimateMemoryUsage(obj) {
const seen = new WeakSet();
function sizeOf(obj) {
if (obj === null || obj === undefined) {
return 0;
}
switch (typeof obj) {
case "boolean":
return 4; // 布尔值通常占用4字节
case "number":
return 8; // JavaScript数字是64位浮点数
case "string":
return obj.length * 2; // UTF-16编码,每个字符2字节
case "object":
if (seen.has(obj)) {
return 0;
}
seen.add(obj);
if (Array.isArray(obj)) {
return obj.reduce((acc, cur) => acc + sizeOf(cur), 0);
}
if (obj instanceof Map || obj instanceof Set) {
let size = 0;
obj.forEach(value => {
if (obj instanceof Map) {
size += sizeOf(value);
}
size += sizeOf(value);
});
return size;
}
// 普通对象
return Object.keys(obj).reduce((acc, key) => {
return acc + sizeOf(key) + sizeOf(obj[key]);
}, 0);
default:
return 0;
}
}
return sizeOf(obj);
}
// 测试不同集合的内存占用
console.log("=== 内存占用分析 ===");
const dataSize = 10000;
// 数组
const arr = [];
for (let i = 0; i < dataSize; i++) {
arr.push(i);
}
console.log(`Array(${dataSize}): 约 ${estimateMemoryUsage(arr)} 字节`);
// Set
const testSet = new Set();
for (let i = 0; i < dataSize; i++) {
testSet.add(i);
}
console.log(`Set(${dataSize}): 约 ${estimateMemoryUsage(testSet)} 字节`);
// Map
const testMap = new Map();
for (let i = 0; i < dataSize; i++) {
testMap.set(`key${i}`, i);
}
console.log(`Map(${dataSize}): 约 ${estimateMemoryUsage(testMap)} 字节`);
// 对象
const testObj = {};
for (let i = 0; i < dataSize; i++) {
testObj[`key${i}`] = i;
}
console.log(`Object(${dataSize}): 约 ${estimateMemoryUsage(testObj)} 字节`);
class CollectionUtils {
// 数组工具
static array = {
// 分块
chunk(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
},
// 去重
unique(array) {
return [...new Set(array)];
},
// 交集
intersect(array1, array2) {
return array1.filter(item => array2.includes(item));
},
// 差集
difference(array1, array2) {
return array1.filter(item => !array2.includes(item));
},
// 并集
union(array1, array2) {
return [...new Set([...array1, ...array2])];
},
// 打乱顺序
shuffle(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
},
// 分组
groupBy(array, key) {
return array.reduce((groups, item) => {
const groupKey = typeof key === "function" ? key(item) : item[key];
if (!groups[groupKey]) {
groups[groupKey] = [];
}
groups[groupKey].push(item);
return groups;
}, {});
},
};
// Map工具
static map = {
// 过滤Map
filter(map, predicate) {
const result = new Map();
for (const [key, value] of map) {
if (predicate(value, key, map)) {
result.set(key, value);
}
}
return result;
},
// Map转对象
toObject(map) {
return Object.fromEntries(map);
},
// 对象转Map
fromObject(obj) {
return new Map(Object.entries(obj));
},
// 合并多个Map
merge(...maps) {
const result = new Map();
for (const map of maps) {
for (const [key, value] of map) {
result.set(key, value);
}
}
return result;
},
};
// Set工具
static set = {
// 过滤Set
filter(set, predicate) {
const result = new Set();
for (const value of set) {
if (predicate(value, value, set)) {
result.add(value);
}
}
return result;
},
// 映射Set
map(set, mapper) {
const result = new Set();
for (const value of set) {
result.add(mapper(value, value, set));
}
return result;
},
};
// 类型化数组工具
static typedArray = {
// 创建指定类型的数组
create(type, length) {
const constructors = {
int8: Int8Array,
uint8: Uint8Array,
int16: Int16Array,
uint16: Uint16Array,
int32: Int32Array,
uint32: Uint32Array,
float32: Float32Array,
float64: Float64Array,
};
const Constructor = constructors[type];
if (!Constructor) {
throw new Error(`Unsupported type: ${type}`);
}
return new Constructor(length);
},
// 合并多个类型化数组
concat(arrays) {
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
const result = new arrays[0].constructor(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
},
};
}
// 使用示例
console.log(CollectionUtils.array.chunk([1, 2, 3, 4, 5], 2)); // [[1, 2], [3, 4], [5]]
console.log(CollectionUtils.array.unique([1, 2, 2, 3, 3, 3])); // [1, 2, 3]
const map1 = new Map([
["a", 1],
["b", 2],
]);
const map2 = new Map([
["b", 3],
["c", 4],
]);
console.log(CollectionUtils.map.merge(map1, map2)); // Map(3) {'a' => 1, 'b' => 3, 'c' => 4}
// 有序Map(保持插入顺序)
class OrderedMap {
constructor(entries = []) {
this._map = new Map();
this._order = [];
for (const [key, value] of entries) {
this.set(key, value);
}
}
set(key, value) {
if (!this._map.has(key)) {
this._order.push(key);
}
this._map.set(key, value);
return this;
}
get(key) {
return this._map.get(key);
}
has(key) {
return this._map.has(key);
}
delete(key) {
if (this._map.delete(key)) {
const index = this._order.indexOf(key);
if (index > -1) {
this._order.splice(index, 1);
}
return true;
}
return false;
}
clear() {
this._map.clear();
this._order.length = 0;
}
get size() {
return this._map.size;
}
*keys() {
for (const key of this._order) {
yield key;
}
}
*values() {
for (const key of this._order) {
yield this._map.get(key);
}
}
*entries() {
for (const key of this._order) {
yield [key, this._map.get(key)];
}
}
forEach(callback, thisArg) {
for (const key of this._order) {
callback.call(thisArg, this._map.get(key), key, this);
}
}
[Symbol.iterator]() {
return this.entries();
}
}
// LRU缓存(最近最少使用)
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) {
return null;
}
// 将访问的元素移到最前面(表示最近使用)
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// 删除最久未使用的元素(Map中的第一个元素)
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
clear() {
this.cache.clear();
}
get size() {
return this.cache.size;
}
}
// 双向映射(Bi-directional Map)
class BiMap {
constructor(entries = []) {
this._forward = new Map();
this._reverse = new Map();
for (const [key, value] of entries) {
this.set(key, value);
}
}
set(key, value) {
// 删除旧的映射
if (this._forward.has(key)) {
const oldValue = this._forward.get(key);
this._reverse.delete(oldValue);
}
if (this._reverse.has(value)) {
const oldKey = this._reverse.get(value);
this._forward.delete(oldKey);
}
this._forward.set(key, value);
this._reverse.set(value, key);
return this;
}
get(key) {
return this._forward.get(key);
}
getKey(value) {
return this._reverse.get(value);
}
has(key) {
return this._forward.has(key);
}
hasValue(value) {
return this._reverse.has(value);
}
delete(key) {
if (this._forward.has(key)) {
const value = this._forward.get(key);
this._forward.delete(key);
this._reverse.delete(value);
return true;
}
return false;
}
deleteValue(value) {
if (this._reverse.has(value)) {
const key = this._reverse.get(value);
this._reverse.delete(value);
this._forward.delete(key);
return true;
}
return false;
}
clear() {
this._forward.clear();
this._reverse.clear();
}
get size() {
return this._forward.size;
}
keys() {
return this._forward.keys();
}
values() {
return this._forward.values();
}
entries() {
return this._forward.entries();
}
[Symbol.iterator]() {
return this.entries();
}
}
// 使用示例
const lru = new LRUCache(3);
lru.put("a", 1);
lru.put("b", 2);
lru.put("c", 3);
lru.get("a"); // 将'a'移到最近使用
lru.put("d", 4); // 'b'被淘汰
const biMap = new BiMap([
["apple", "苹果"],
["banana", "香蕉"],
]);
console.log(biMap.get("apple")); // '苹果'
console.log(biMap.getKey("香蕉")); // 'banana'
数组用于有序数据,Map 用于键值对,Set 用于唯一值集合,类型化数组用于二进制数据