JavaScript 数组方法全面解析
一、数组基础
JavaScript 数组是用于存储多个值的有序集合,具有以下特点:
- 可以存储任意类型的值
- 大小可动态调整
- 具有类型化的方法用于常见操作
创建数组
// 字面量创建 const arr1 = []; const arr2 = [1, 2, 3]; // 构造函数创建 const arr3 = new Array(); const arr4 = new Array(1, 2, 3); const arr5 = new Array(5); // 创建长度为5的空数组
二、会修改原数组的方法
1. push() - 末尾添加元素
const fruits = ['apple', 'banana']; const count = fruits.push('orange'); console.log(fruits); // ['apple', 'banana', 'orange'] console.log(count); // 3 (返回新长度)
2. pop() - 移除末尾元素
const fruits = ['apple', 'banana', 'orange']; const last = fruits.pop(); console.log(fruits); // ['apple', 'banana'] console.log(last); // 'orange' (返回被移除的元素)
3. unshift() - 头部添加元素
const fruits = ['banana', 'orange']; const count = fruits.unshift('apple'); console.log(fruits); // ['apple', 'banana', 'orange'] console.log(count); // 3 (返回新长度)
4. shift() - 移除头部元素
const fruits = ['apple', 'banana', 'orange']; const first = fruits.shift(); console.log(fruits); // ['banana', 'orange'] console.log(first); // 'apple' (返回被移除的元素)
5. splice() - 添加/删除元素
const fruits = ['apple', 'banana', 'orange', 'grape']; // 删除元素: splice(startIndex, deleteCount) const removed = fruits.splice(1, 2); console.log(fruits); // ['apple', 'grape'] console.log(removed); // ['banana', 'orange'] // 添加元素: splice(index, 0, elem1, elem2, ...) fruits.splice(1, 0, 'banana', 'orange'); console.log(fruits); // ['apple', 'banana', 'orange', 'grape'] // 替换元素: splice(index, deleteCount, elem1, elem2, ...) const replaced = fruits.splice(1, 2, 'mango', 'peach'); console.log(fruits); // ['apple', 'mango', 'peach', 'grape'] console.log(replaced); // ['banana', 'orange']
6. reverse() - 反转数组顺序
const nums = [1, 2, 3]; nums.reverse(); console.log(nums); // [3, 2, 1] (返回反转后的数组)
7. sort() - 数组排序
const fruits = ['banana', 'apple', 'orange']; fruits.sort(); console.log(fruits); // ['apple', 'banana', 'orange'] (返回排序后的数组) // 数字排序需要比较函数 const nums = [10, 5, 40, 25]; nums.sort((a, b) => a - b); console.log(nums); // [5, 10, 25, 40]
8. fill() - 填充数组
const arr = [1, 2, 3, 4]; arr.fill(0, 1, 3); // (value, start, end) console.log(arr); // [1, 0, 0, 4] // 填充整个数组 const newArr = new Array(3).fill('x'); console.log(newArr); // ['x', 'x', 'x']
9. copyWithin() - 复制数组元素
const arr = [1, 2, 3, 4, 5]; arr.copyWithin(0, 3, 4); // (target, start, end) console.log(arr); // [4, 2, 3, 4, 5]
三、不会修改原数组的方法
1. concat() - 合并数组
const arr1 = [1, 2]; const arr2 = ['a', 'b']; const arr3 = arr1.concat(arr2, 3, [4, 5]); console.log(arr1); // [1, 2] (原数组不变) console.log(arr3); // [1, 2, 'a', 'b', 3, 4, 5]
2. slice() - 提取子数组
const fruits = ['apple', 'banana', 'orange', 'grape']; const citrus = fruits.slice(1, 3); // (start, end) console.log(fruits); // ['apple', 'banana', 'orange', 'grape'] (原数组不变) console.log(citrus); // ['banana', 'orange']
3. join() - 数组转字符串
const fruits = ['apple', 'banana', 'orange']; const str = fruits.join(' - '); console.log(str); // 'apple - banana - orange' (返回字符串)
4. indexOf() / lastIndexOf() - 查找元素索引
const fruits = ['apple', 'banana', 'orange', 'banana']; console.log(fruits.indexOf('banana')); // 1 console.log(fruits.lastIndexOf('banana')); // 3 console.log(fruits.indexOf('grape')); // -1 (未找到)
5. includes() - 检查是否包含
const fruits = ['apple', 'banana', 'orange']; console.log(fruits.includes('banana')); // true console.log(fruits.includes('grape')); // false
6. find() / findIndex() - 查找元素
const users = [ {id: 1, name: 'John'}, {id: 2, name: 'Jane'}, {id: 3, name: 'Bob'} ]; const user = users.find(u => u.id === 2); console.log(user); // {id: 2, name: 'Jane'} const index = users.findIndex(u => u.name === 'Bob'); console.log(index); // 2
7. filter() - 过滤数组
const nums = [1, 2, 3, 4, 5]; const evens = nums.filter(n => n % 2 === 0); console.log(evens); // [2, 4] (返回新数组)
8. map() - 映射新数组
const nums = [1, 2, 3]; const squared = nums.map(n => n * n); console.log(squared); // [1, 4, 9]
9. reduce() / reduceRight() - 归并数组
const nums = [1, 2, 3, 4]; const sum = nums.reduce((acc, cur) => acc + cur, 0); console.log(sum); // 10 // 计算数组元素出现次数 const fruits = ['apple', 'banana', 'apple', 'orange']; const count = fruits.reduce((acc, fruit) => { acc[fruit] = (acc[fruit] || 0) + 1; return acc; }, {}); console.log(count); // {apple: 2, banana: 1, orange: 1}
10. some() / every() - 测试数组
const nums = [1, 2, 3, 4]; console.log(nums.some(n => n > 3)); // true (至少一个元素满足条件) console.log(nums.every(n => n > 0)); // true (所有元素满足条件)
11. flat() - 数组扁平化
const arr = [1, [2, [3, [4]]]]; console.log(arr.flat()); // [1, 2, [3, [4]]] console.log(arr.flat(2)); // [1, 2, 3, [4]] console.log(arr.flat(Infinity)); // [1, 2, 3, 4]
12. flatMap() - 映射后扁平化
const arr = [1, 2, 3]; const result = arr.flatMap(x => [x, x * 2]); console.log(result); // [1, 2, 2, 4, 3, 6]
四、数组遍历方法
1. forEach() - 遍历数组
const fruits = ['apple', 'banana', 'orange']; fruits.forEach((fruit, index) => { console.log(`${index}: ${fruit}`); }); // 0: apple // 1: banana // 2: orange
2. entries() / keys() / values() - 迭代器方法
const arr = ['a', 'b', 'c']; // 键值对迭代器 for (const [index, element] of arr.entries()) { console.log(index, element); } // 键迭代器 for (const index of arr.keys()) { console.log(index); } // 值迭代器 for (const element of arr.values()) { console.log(element); }
五、其他实用方法
1. Array.from() - 类数组转数组
const arrayLike = {0: 'a', 1: 'b', length: 2}; const arr = Array.from(arrayLike); console.log(arr); // ['a', 'b'] // 从字符串创建 console.log(Array.from('hello')); // ['h', 'e', 'l', 'l', 'o']
2. Array.of() - 创建数组
console.log(Array.of(1, 2, 3)); // [1, 2, 3] console.log(Array.of(3)); // [3] (不同于 new Array(3))
3. isArray() - 检查是否为数组
console.log(Array.isArray([])); // true console.log(Array.isArray({})); // false
六、性能考虑
- 修改原数组的方法(push/pop/shift/unshift/splice等)在大型数组上可能性能较差
- 创建新数组的方法(map/filter/slice等)通常更安全但会产生内存开销
- 遍历方法(forEach/reduce等)比传统的for循环稍慢,但代码更清晰
七、总结图表
| 方法分类 | 方法名 | 是否修改原数组 | 返回值 |
|---|---|---|---|
| 修改方法 | push() | ✔️ | 新长度 |
| pop() | ✔️ | 被移除的元素 | |
| unshift() | ✔️ | 新长度 | |
| shift() | ✔️ | 被移除的元素 | |
| splice() | ✔️ | 被删除元素的数组 | |
| reverse() | ✔️ | 反转后的数组 | |
| sort() | ✔️ | 排序后的数组 | |
| fill() | ✔️ | 修改后的数组 | |
| copyWithin() | ✔️ | 修改后的数组 | |
| 不修改方法 | concat() | ❌ | 新数组 |
| slice() | ❌ | 子数组 | |
| join() | ❌ | 字符串 | |
| indexOf()/lastIndexOf() | ❌ | 索引或-1 | |
| includes() | ❌ | 布尔值 | |
| find()/findIndex() | ❌ | 元素或索引 | |
| filter() | ❌ | 新数组 | |
| map() | ❌ | 新数组 | |
| reduce()/reduceRight() | ❌ | 累积结果 | |
| some()/every() | ❌ | 布尔值 | |
| flat()/flatMap() | ❌ | 新数组 | |
| 遍历方法 | forEach() | ❌ | undefined |
| entries()/keys()/values() | ❌ | 迭代器 |
掌握这些数组方法可以让你更高效地处理数据集合,根据是否需要修改原数组和具体需求选择合适的方法。