解构赋值可以从数组中提取值并赋给变量。
const arr = [1, 2, 3];
// 基本解构
const [a, b, c] = arr;
console.log(a, b, c); // 1 2 3
// 跳过元素
const [first, , third] = arr;
console.log(first, third); // 1 3
// 剩余元素
const [head, ...tail] = arr;
console.log(head); // 1
console.log(tail); // [2, 3]
const arr = [1, 2];
// 默认值
const [a, b, c = 3] = arr;
console.log(a, b, c); // 1 2 3
// undefined时使用默认值
const [x = 10, y = 20] = [undefined, 2];
console.log(x, y); // 10 2
let a = 1;
let b = 2;
// 交换值
[a, b] = [b, a];
console.log(a, b); // 2 1
const nested = [1, [2, 3], 4];
const [a, [b, c], d] = nested;
console.log(a, b, c, d); // 1 2 3 4
function getCoords() {
return [10, 20];
}
const [x, y] = getCoords();
console.log(x, y); // 10 20
展开运算符(...)可以展开数组。
const arr = [1, 2, 3];
// 展开数组
console.log(...arr); // 1 2 3
// 复制数组
const copy = [...arr];
console.log(copy); // [1, 2, 3]
// 合并数组
const arr2 = [4, 5, 6];
const merged = [...arr, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]
const numbers = [1, 2, 3, 4, 5];
// 展开作为参数
console.log(Math.max(...numbers)); // 5
console.log(Math.min(...numbers)); // 1
// 等价于
Math.max.apply(null, numbers);
const arr = [2, 3, 4];
// 开头添加
const newArr1 = [1, ...arr]; // [1, 2, 3, 4]
// 末尾添加
const newArr2 = [...arr, 5]; // [2, 3, 4, 5]
// 中间插入
const newArr3 = [...arr.slice(0, 2), 2.5, ...arr.slice(2)];
// [2, 3, 2.5, 4]
// NodeList转数组
const divs = document.querySelectorAll("div");
const divArray = [...divs];
// arguments转数组
function foo() {
const args = [...arguments];
}
// 字符串转数组
const chars = [..."东巴文"]; // ["东", "巴", "文"]
const arr = [1, 2, { name: "东巴文" }];
// slice
const copy1 = arr.slice();
// 展开运算符
const copy2 = [...arr];
// Array.from
const copy3 = Array.from(arr);
// concat
const copy4 = arr.concat();
// 注意:都是浅拷贝
copy1[2].name = "JavaScript";
console.log(arr[2].name); // "JavaScript"
const arr = [1, 2, { name: "东巴文", nested: [3, 4] }];
// JSON方法(有局限性)
const deepCopy1 = JSON.parse(JSON.stringify(arr));
// structuredClone(现代浏览器)
const deepCopy2 = structuredClone(arr);
// 递归实现
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(item => deepClone(item));
}
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
| 方法 | 深度 | 函数/undefined | 循环引用 | 东巴文建议 |
|---|---|---|---|---|
| slice/spread | 浅 | 保留 | 支持 | 简单场景 |
| JSON | 深 | 丢失 | 报错 | 纯数据 |
| structuredClone | 深 | 报错 | 支持 | 现代环境 |
将多维数组转为一维数组。
const nested = [1, [2, 3], [4, [5, 6, [7, 8]]]];
nested.flat(); // [1, 2, 3, 4, [5, 6, [7, 8]]]
nested.flat(2); // [1, 2, 3, 4, 5, 6, [7, 8]]
nested.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8]
function flatten(arr) {
const result = [];
for (const item of arr) {
if (Array.isArray(item)) {
result.push(...flatten(item));
} else {
result.push(item);
}
}
return result;
}
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]
function flatten(arr) {
return arr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, []);
}
function flattenDepth(arr, depth = 1) {
if (depth === 0) return arr;
return arr.reduce((acc, cur) => {
return acc.concat(
Array.isArray(cur) ? flattenDepth(cur, depth - 1) : cur
);
}, []);
}
flattenDepth([1, [2, [3, [4]]]], 1); // [1, 2, [3, [4]]]
flattenDepth([1, [2, [3, [4]]]], 2); // [1, 2, 3, [4]]
const arr = [1, 2, 2, 3, 3, 3, 4];
// 使用Set
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3, 4]
// 或使用Array.from
const unique2 = Array.from(new Set(arr));
const arr = [1, 2, 2, 3, 3, 3, 4];
const unique = arr.filter((item, index) => {
return arr.indexOf(item) === index;
});
const arr = [1, 2, 2, 3, 3, 3, 4];
const unique = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
const users = [
{ id: 1, name: "东巴文" },
{ id: 2, name: "张三" },
{ id: 1, name: "东巴文" }
];
// 按id去重
const unique = users.filter((user, index, arr) => {
return arr.findIndex(u => u.id === user.id) === index;
});
// 使用Map
const unique2 = [...new Map(users.map(u => [u.id, u])).values()];
function bubbleSort(arr) {
const result = [...arr];
const len = result.length;
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (result[j] > result[j + 1]) {
[result[j], result[j + 1]] = [result[j + 1], result[j]];
}
}
}
return result;
}
function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[Math.floor(arr.length / 2)];
const left = arr.filter(x => x < pivot);
const middle = arr.filter(x => x === pivot);
const right = arr.filter(x => x > pivot);
return [...quickSort(left), ...middle, ...quickSort(right)];
}
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
const result = [];
let i = 0, j = 0;
while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
result.push(left[i++]);
} else {
result.push(right[j++]);
}
}
return result.concat(left.slice(i)).concat(right.slice(j));
}
| 算法 | 时间复杂度 | 空间复杂度 | 稳定性 | 东巴文建议 |
|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(1) | 稳定 | 学习用 |
| 快速排序 | O(n log n) | O(log n) | 不稳定 | 实际使用 |
| 归并排序 | O(n log n) | O(n) | 稳定 | 需要稳定时 |
| 原生sort | O(n log n) | O(1) | 取决于引擎 | 首选 |
TypedArray是处理二进制数据的数组类型。
| 类型 | 说明 | 字节数 |
|---|---|---|
| Int8Array | 8位有符号整数 | 1 |
| Uint8Array | 8位无符号整数 | 1 |
| Int16Array | 16位有符号整数 | 2 |
| Uint16Array | 16位无符号整数 | 2 |
| Int32Array | 32位有符号整数 | 4 |
| Uint32Array | 32位无符号整数 | 4 |
| Float32Array | 32位浮点数 | 4 |
| Float64Array | 64位浮点数 | 8 |
// 从长度创建
const int8 = new Int8Array(5); // [0, 0, 0, 0, 0]
// 从数组创建
const int16 = new Int16Array([1, 2, 3, 4, 5]);
// 从ArrayBuffer创建
const buffer = new ArrayBuffer(8);
const int32 = new Int32Array(buffer);
// 从另一个TypedArray创建
const copy = new Int8Array(int8);
const arr = new Int32Array([1, 2, 3, 4, 5]);
// 访问
arr[0]; // 1
arr.at(-1); // 5
// 修改
arr[0] = 10;
// 方法
arr.length; // 5
arr.set([6, 7], 3); // 从索引3开始设置
arr.subarray(1, 3); // 返回视图
// 遍历
for (const num of arr) {
console.log(num);
}
// 创建缓冲区
const buffer = new ArrayBuffer(16); // 16字节
// 创建视图
const int32 = new Int32Array(buffer); // 4个32位整数
const int8 = new Int8Array(buffer); // 16个8位整数
// 共享同一块内存
int32[0] = 0x12345678;
console.log(int8[0]); // 0x78(小端序)
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
// 设置值
view.setInt8(0, 127);
view.setInt16(1, 32767, true); // true表示小端序
view.setFloat64(4, 3.14159);
// 读取值
view.getInt8(0);
view.getInt16(1, true);
view.getFloat64(4);
// 处理二进制文件
const file = input.files[0];
const buffer = await file.arrayBuffer();
const bytes = new Uint8Array(buffer);
// WebSocket二进制数据
const ws = new WebSocket(url);
ws.binaryType = "arraybuffer";
ws.onmessage = (event) => {
const data = new Uint8Array(event.data);
};
// Canvas像素操作
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(0, 0, 100, 100);
const pixels = new Uint8ClampedArray(imageData.data);
function shuffle(arr) {
const result = [...arr];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
}
shuffle([1, 2, 3, 4, 5]);
function chunk(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
chunk([1, 2, 3, 4, 5, 6], 2); // [[1, 2], [3, 4], [5, 6]]
function difference(arr1, arr2) {
return arr1.filter(x => !arr2.includes(x));
}
difference([1, 2, 3, 4], [2, 4]); // [1, 3]
function intersection(arr1, arr2) {
return arr1.filter(x => arr2.includes(x));
}
intersection([1, 2, 3, 4], [2, 3, 5]); // [2, 3]
function union(arr1, arr2) {
return [...new Set([...arr1, ...arr2])];
}
union([1, 2, 3], [2, 3, 4]); // [1, 2, 3, 4]
掌握了数组高级应用后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🚀 东巴文寄语:数组高级应用是提升代码质量的关键,掌握解构、展开运算符、深浅拷贝、去重、排序等技巧,能让你写出更优雅、更高效的代码。在 db-w.cn,我们帮你进阶!