10.JavaScript 数组方法完全指南(完整版)
📋 速查对照表(标注是否会改变原数组)
基本信息
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果 |
.length |
获取数组长度 |
❌ 否 |
[1,2,3].length |
3 |
Array.isArray() |
判断是否为数组 |
❌ 否 |
Array.isArray([]) |
true |
查找与判断
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果 |
.indexOf() |
查找元素首次出现的位置 |
❌ 否 |
[1,2,2].indexOf(2) |
1 |
.lastIndexOf() |
查找元素最后一次出现的位置 |
❌ 否 |
[1,2,2].lastIndexOf(2) |
2 |
.includes() |
检查是否包含某元素 |
❌ 否 |
[1,2,3].includes(2) |
true |
.find() |
查找第一个符合条件的元素 |
❌ 否 |
[1,2,3].find(x=>x>1) |
2 |
.findIndex() |
查找第一个符合条件的元素位置 |
❌ 否 |
[1,2,3].findIndex(x=>x>1) |
1 |
.some() |
检查是否有元素满足条件 |
❌ 否 |
[1,2,3].some(x=>x>2) |
true |
.every() |
检查是否所有元素都满足条件 |
❌ 否 |
[1,2,3].every(x=>x>0) |
true |
添加与删除
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果(原数组变化) |
.push() |
在末尾添加元素 |
✅ 是 |
arr=[1,2]; arr.push(3) |
arr变成[1,2,3] |
.pop() |
删除最后一个元素 |
✅ 是 |
arr=[1,2,3]; arr.pop() |
arr变成[1,2] |
.unshift() |
在开头添加元素 |
✅ 是 |
arr=[2,3]; arr.unshift(1) |
arr变成[1,2,3] |
.shift() |
删除第一个元素 |
✅ 是 |
arr=[1,2,3]; arr.shift() |
arr变成[2,3] |
.splice() |
添加/删除任意位置元素 |
✅ 是 |
arr=[1,2,3]; arr.splice(1,1) |
arr变成[1,3] |
截取与连接
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果(原数组不变) |
.slice() |
截取部分数组 |
❌ 否 |
arr=[1,2,3,4]; arr.slice(1,3) |
返回[2,3],arr不变 |
.concat() |
连接多个数组 |
❌ 否 |
[1].concat([2]) |
返回[1,2],原数组不变 |
.join() |
将数组转为字符串 |
❌ 否 |
[1,2,3].join("-") |
返回"1-2-3",数组不变 |
.toString() |
数组转字符串 |
❌ 否 |
[1,2,3].toString() |
返回"1,2,3",数组不变 |
排序与反转
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果(原数组变化) |
.sort() |
排序数组 |
✅ 是 |
arr=[3,1,2]; arr.sort() |
arr变成[1,2,3] |
.reverse() |
反转数组顺序 |
✅ 是 |
arr=[1,2,3]; arr.reverse() |
arr变成[3,2,1] |
遍历与处理
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果 |
.forEach() |
遍历数组每个元素 |
❌ 否 |
[1,2].forEach(x=>console.log(x)) |
输出1,2 |
.map() |
创建新数组(映射) |
❌ 否 |
[1,2].map(x=>x*2) |
返回[2,4] |
.filter() |
过滤符合条件的元素 |
❌ 否 |
[1,2,3].filter(x=>x>1) |
返回[2,3] |
.reduce() |
累积计算 |
❌ 否 |
[1,2,3].reduce((a,b)=>a+b) |
返回6 |
.reduceRight() |
从右向左累积计算 |
❌ 否 |
[1,2,3].reduceRight((a,b)=>a-b) |
返回0 |
ES6+ 新增方法
| 方法 |
功能 |
是否改变原数组 |
示例 |
结果 |
.flat() |
扁平化数组 |
❌ 否 |
[1,[2]].flat() |
返回[1,2] |
.flatMap() |
映射后扁平化 |
❌ 否 |
["ab","cd"].flatMap(x=>x.split("")) |
返回["a","b","c","d"] |
.fill() |
填充数组 |
✅ 是 |
arr=[1,2,3]; arr.fill(0) |
arr变成[0,0,0] |
🔴 重要概念:哪些方法会改变原数组?
会改变原数组的方法(破坏性方法)
// 这些方法会直接修改原数组
let arr = [1, 2, 3];
arr.push(4); // 原数组变成 [1,2,3,4]
arr.pop(); // 原数组变成 [1,2,3]
arr.shift(); // 原数组变成 [2,3]
arr.unshift(0); // 原数组变成 [0,2,3]
arr.splice(1, 1); // 原数组变成 [0,3]
arr.reverse(); // 原数组变成 [3,0]
arr.sort(); // 原数组变成 [0,3]
arr.fill(9); // 原数组变成 [9,9]
console.log(arr); // [9,9](原数组已被修改)
不会改变原数组的方法(非破坏性方法)
// 这些方法返回新结果,原数组不变
let arr = [1, 2, 3];
let newArr1 = arr.slice(1); // 返回 [2,3],arr 还是 [1,2,3]
let newArr2 = arr.concat([4]); // 返回 [1,2,3,4],arr 还是 [1,2,3]
let str = arr.join("-"); // 返回 "1-2-3",arr 还是 [1,2,3]
let newArr3 = arr.map(x=>x*2); // 返回 [2,4,6],arr 还是 [1,2,3]
let newArr4 = arr.filter(x=>x>1);// 返回 [2,3],arr 还是 [1,2,3]
console.log(arr); // [1,2,3](原数组保持不变)
一、什么是数组?
数组就像一个装东西的盒子,可以按顺序存放多个数据。
// 创建数组的三种方式
let fruits = ["苹果", "香蕉", "橙子"]; // 最常用
let numbers = new Array(1, 2, 3); // 使用构造函数
let mixed = [1, "hello", true]; // 可以混合不同类型
console.log(fruits); // ["苹果", "香蕉", "橙子"]
console.log(fruits[0]); // "苹果"(第一个元素)
console.log(fruits.length); // 3(数组长度)
二、查找与判断方法
1. .indexOf() – 查找元素位置(不改变原数组)
let fruits = ["苹果", "香蕉", "橙子", "香蕉"];
console.log(fruits.indexOf("香蕉")); // 1(第一次出现的位置)
console.log(fruits.indexOf("西瓜")); // -1(没找到)
console.log(fruits.indexOf("香蕉", 2)); // 3(从位置2开始找)
console.log(fruits); // ["苹果", "香蕉", "橙子", "香蕉"](原数组不变)
2. .lastIndexOf() – 从后往前查找(不改变原数组)
let fruits = ["苹果", "香蕉", "橙子", "香蕉"];
console.log(fruits.lastIndexOf("香蕉")); // 3(最后一次出现的位置)
console.log(fruits.lastIndexOf("香蕉", 2)); // 1(从位置2往前找)
3. .includes() – 检查是否包含(不改变原数组)
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // true(包含3)
console.log(numbers.includes(6)); // false(不包含6)
console.log(numbers.includes(2, 2)); // false(从位置2开始找2)
4. .find() – 查找第一个符合条件的元素(不改变原数组)
let numbers = [5, 12, 8, 130, 44];
// 查找第一个大于10的数字
let found = numbers.find(function(num) {
return num > 10;
});
console.log(found); // 12(第一个大于10的数字)
// 使用箭头函数更简洁
let found2 = numbers.find(num => num > 100);
console.log(found2); // 130
5. .findIndex() – 查找第一个符合条件的元素位置(不改变原数组)
let numbers = [5, 12, 8, 130, 44];
// 查找第一个大于10的数字的位置
let index = numbers.findIndex(num => num > 10);
console.log(index); // 1(12的位置)
// 找不到返回-1
let notFound = numbers.findIndex(num => num > 1000);
console.log(notFound); // -1
6. Array.isArray() – 判断是否为数组(不改变原数组)
let arr = [1, 2, 3];
let str = "hello";
let obj = {a: 1};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(str)); // false
console.log(Array.isArray(obj)); // false
// 注意:typeof 不能准确判断数组
console.log(typeof arr); // "object"(不够准确)
7. .some() – 检查是否有元素满足条件(不改变原数组)
let numbers = [1, 2, 3, 4, 5];
// 检查是否有偶数
let hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true(2和4是偶数)
// 检查是否有负数
let hasNegative = numbers.some(num => num < 0);
console.log(hasNegative); // false(没有负数)
8. .every() – 检查是否所有元素都满足条件(不改变原数组)
let numbers = [1, 2, 3, 4, 5];
// 检查是否都是正数
let allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true(都是正数)
// 检查是否都小于10
let allSmall = numbers.every(num => num < 10);
console.log(allSmall); // true(都小于10)
// 检查是否都是偶数
let allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // false(1,3,5不是偶数)
三、添加与删除方法
9. .push() – 在末尾添加元素(会改变原数组)
let fruits = ["苹果", "香蕉"];
// 添加一个元素
fruits.push("橙子");
console.log(fruits); // ["苹果", "香蕉", "橙子"]
// 添加多个元素
fruits.push("葡萄", "西瓜");
console.log(fruits); // ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
// push() 返回新数组长度
let length = fruits.push("芒果");
console.log(length); // 6
10. .pop() – 删除最后一个元素(会改变原数组)
let fruits = ["苹果", "香蕉", "橙子"];
// 删除最后一个元素
let removed = fruits.pop();
console.log(removed); // "橙子"(被删除的元素)
console.log(fruits); // ["苹果", "香蕉"]
// 空数组调用pop()
let empty = [];
console.log(empty.pop()); // undefined
11. .unshift() – 在开头添加元素(会改变原数组)
let numbers = [2, 3, 4];
// 在开头添加一个元素
numbers.unshift(1);
console.log(numbers); // [1, 2, 3, 4]
// 添加多个元素
numbers.unshift(-1, 0);
console.log(numbers); // [-1, 0, 1, 2, 3, 4]
12. .shift() – 删除第一个元素(会改变原数组)
let fruits = ["苹果", "香蕉", "橙子"];
// 删除第一个元素
let first = fruits.shift();
console.log(first); // "苹果"(被删除的元素)
console.log(fruits); // ["香蕉", "橙子"]
13. .splice() – 多功能添加/删除(会改变原数组)
let fruits = ["苹果", "香蕉", "橙子", "葡萄"];
// 1. 删除元素:splice(开始位置, 删除数量)
let removed1 = fruits.splice(1, 2);
console.log(removed1); // ["香蕉", "橙子"](被删除的)
console.log(fruits); // ["苹果", "葡萄"]
// 2. 添加元素:splice(开始位置, 0, 新元素...)
fruits = ["苹果", "香蕉", "葡萄"];
fruits.splice(2, 0, "橙子", "西瓜");
console.log(fruits); // ["苹果", "香蕉", "橙子", "西瓜", "葡萄"]
// 3. 替换元素:splice(开始位置, 删除数量, 新元素...)
fruits = ["苹果", "香蕉", "橙子"];
fruits.splice(1, 1, "葡萄", "西瓜");
console.log(fruits); // ["苹果", "葡萄", "西瓜", "橙子"]
四、截取与连接方法
14. .slice() – 截取部分数组(不改变原数组)
let fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"];
// 截取位置1到3(不包括3)
let part1 = fruits.slice(1, 3);
console.log(part1); // ["香蕉", "橙子"]
// 从位置2截取到末尾
let part2 = fruits.slice(2);
console.log(part2); // ["橙子", "葡萄", "西瓜"]
// 使用负数(从末尾计算)
let part3 = fruits.slice(-3, -1);
console.log(part3); // ["橙子", "葡萄"]
// 注意:slice()不改变原数组
console.log(fruits); // 原数组不变:["苹果","香蕉","橙子","葡萄","西瓜"]
15. .concat() – 连接多个数组(不改变原数组)
let arr1 = [1, 2];
let arr2 = [3, 4];
let arr3 = [5, 6];
// 连接两个数组
let combined = arr1.concat(arr2);
console.log(combined); // [1, 2, 3, 4]
// 连接多个数组
let all = arr1.concat(arr2, arr3);
console.log(all); // [1, 2, 3, 4, 5, 6]
// 也可以连接值
let withValues = arr1.concat(7, 8);
console.log(withValues); // [1, 2, 7, 8]
// 原数组不变
console.log(arr1); // [1, 2]
16. .join() – 数组转字符串(不改变原数组)
let fruits = ["苹果", "香蕉", "橙子"];
// 默认用逗号连接
console.log(fruits.join()); // "苹果,香蕉,橙子"
// 指定连接符
console.log(fruits.join("-")); // "苹果-香蕉-橙子"
console.log(fruits.join("和")); // "苹果和香蕉和橙子"
console.log(fruits.join("")); // "苹果香蕉橙子"
// 注意:null/undefined会变成空字符串
let mixed = [1, null, 2, undefined, 3];
console.log(mixed.join("-")); // "1--2--3"
17. .toString() – 数组转字符串(不改变原数组)
let numbers = [1, 2, 3];
console.log(numbers.toString()); // "1,2,3"
console.log([1, "hello", true].toString()); // "1,hello,true"
// 与join()的区别
let arr = [1, 2, 3];
console.log(arr.toString() === arr.join()); // true(默认逗号连接)
// 嵌套数组
console.log([1, [2, 3]].toString()); // "1,2,3"(会自动展平)
五、排序与反转方法
18. .sort() – 排序数组(会改变原数组)
let fruits = ["香蕉", "苹果", "橙子", "葡萄"];
// 默认按字符串排序(字母顺序)
fruits.sort();
console.log(fruits); // ["橙子", "葡萄", "苹果", "香蕉"](拼音排序)
let numbers = [10, 5, 40, 25, 100, 1];
// 默认排序(按字符串比较)
numbers.sort();
console.log(numbers); // [1, 10, 100, 25, 40, 5](不是按数字大小!)
// 正确排序数字
numbers.sort(function(a, b) {
return a - b; // 升序排序
});
console.log(numbers); // [1, 5, 10, 25, 40, 100]
// 降序排序
numbers.sort((a, b) => b - a);
console.log(numbers); // [100, 40, 25, 10, 5, 1]
19. .reverse() – 反转数组顺序(会改变原数组)
let numbers = [1, 2, 3, 4, 5];
// 反转数组
numbers.reverse();
console.log(numbers); // [5, 4, 3, 2, 1]
// 会改变原数组
let fruits = ["苹果", "香蕉", "橙子"];
fruits.reverse();
console.log(fruits); // ["橙子", "香蕉", "苹果"]
六、遍历与处理方法
20. .forEach() – 遍历数组(不改变原数组)
let fruits = ["苹果", "香蕉", "橙子"];
// 遍历每个元素
fruits.forEach(function(fruit, index, array) {
console.log(`${index}: ${fruit}`);
});
// 输出:
// 0: 苹果
// 1: 香蕉
// 2: 橙子
// 使用箭头函数
fruits.forEach((fruit, index) => {
console.log(`${index}号水果是${fruit}`);
});
console.log(fruits); // ["苹果","香蕉","橙子"](原数组不变)
21. .filter() – 过滤数组(不改变原数组)
let numbers = [1, 2, 3, 4, 5, 6];
// 过滤出偶数
let evens = numbers.filter(function(num) {
return num % 2 === 0;
});
console.log(evens); // [2, 4, 6]
// 过滤出大于3的数字
let bigNumbers = numbers.filter(num => num > 3);
console.log(bigNumbers); // [4, 5, 6]
// 不改变原数组
console.log(numbers); // [1, 2, 3, 4, 5, 6](原数组不变)
22. .map() – 映射新数组(不改变原数组)
let numbers = [1, 2, 3, 4, 5];
// 每个数字乘以2
let doubled = numbers.map(function(num) {
return num * 2;
});
console.log(doubled); // [2, 4, 6, 8, 10]
// 转换为字符串
let strings = numbers.map(num => `数字${num}`);
console.log(strings); // ["数字1", "数字2", "数字3", "数字4", "数字5"]
// 处理对象数组
let users = [
{name: "张三", age: 25},
{name: "李四", age: 30}
];
let names = users.map(user => user.name);
console.log(names); // ["张三", "李四"]
console.log(numbers); // [1,2,3,4,5](原数组不变)
23. .reduce() – 累积计算(不改变原数组)
let numbers = [1, 2, 3, 4, 5];
// 求和
let sum = numbers.reduce(function(total, current) {
return total + current;
}, 0);
console.log(sum); // 15(0+1+2+3+4+5)
// 求最大值
let max = numbers.reduce((maxNum, current) => {
return current > maxNum ? current : maxNum;
}, numbers[0]);
console.log(max); // 5
// 统计字符出现次数
let words = ["apple", "banana", "apple", "orange", "banana", "apple"];
let count = words.reduce(function(obj, word) {
obj[word] = (obj[word] || 0) + 1;
return obj;
}, {});
console.log(count); // {apple: 3, banana: 2, orange: 1}
24. .reduceRight() – 从右向左累积(不改变原数组)
let numbers = [1, 2, 3, 4];
// 从右向左计算
let result = numbers.reduceRight(function(total, current) {
return total - current;
});
console.log(result); // -2(4-3-2-1 = -2)
// 对比reduce()从左向右
let result2 = numbers.reduce((total, current) => total - current);
console.log(result2); // -8(1-2-3-4 = -8)
七、ES6+ 新增方法
25. .flat() – 扁平化数组(ES2019,不改变原数组)
// 将嵌套数组"压平"
let 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](完全压平)
// 移除空位
let sparse = [1, , 3, , 5];
console.log(sparse.flat()); // [1, 3, 5]
console.log(nested); // 原数组不变:[1, [2, [3, [4]]]]
26. .flatMap() – 映射后扁平化(ES2019,不改变原数组)
// 先map再flat(1)
let phrases = ["hello world", "good morning"];
let words = phrases.flatMap(phrase => phrase.split(" "));
console.log(words); // ["hello", "world", "good", "morning"]
// 传统写法对比
let words2 = phrases.map(phrase => phrase.split(" ")).flat();
console.log(words2); // 相同结果
console.log(phrases); // 原数组不变:["hello world", "good morning"]
27. .fill() – 填充数组(ES6,会改变原数组)
// 创建并填充数组
let arr1 = new Array(5).fill(0);
console.log(arr1); // [0, 0, 0, 0, 0]
// 填充部分区域
let arr2 = [1, 2, 3, 4, 5];
arr2.fill(9, 1, 3); // 从位置1到3(不包括3)填充9
console.log(arr2); // [1, 9, 9, 4, 5](原数组被修改)
28. .from() – 从类数组创建数组(不改变原数组)
// 从字符串创建数组
console.log(Array.from("hello")); // ["h", "e", "l", "l", "o"]
// 从Set创建数组
let set = new Set([1, 2, 3, 3, 2]);
console.log(Array.from(set)); // [1, 2, 3](去重)
// 从类数组对象创建
let arrayLike = {0: "a", 1: "b", 2: "c", length: 3};
console.log(Array.from(arrayLike)); // ["a", "b", "c"]
// 使用映射函数
console.log(Array.from([1, 2, 3], x => x * 2)); // [2, 4, 6]
八、实际应用示例
示例1:购物车操作(会改变原数组)
let cart = ["苹果", "香蕉", "橙子"];
// 添加商品(会改变cart)
cart.push("葡萄"); // cart变成 ["苹果","香蕉","橙子","葡萄"]
cart.unshift("西瓜"); // cart变成 ["西瓜","苹果","香蕉","橙子","葡萄"]
// 删除商品(会改变cart)
cart.pop(); // cart变成 ["西瓜","苹果","香蕉","橙子"]
cart.splice(1, 1); // cart变成 ["西瓜","香蕉","橙子"]
console.log(cart); // ["西瓜","香蕉","橙子"]
示例2:数据分析(不改变原数组)
let scores = [85, 92, 78, 95, 88];
// 创建副本进行分析(不改变原数据)
let sortedScores = scores.slice().sort((a,b)=>b-a); // 降序排序
let topScores = scores.filter(score => score >= 90); // 筛选优秀
let average = scores.reduce((sum,score)=>sum+score)/scores.length; // 计算平均分
console.log("原数据:", scores); // [85,92,78,95,88](不变)
console.log("排序后:", sortedScores); // [95,92,88,85,78]
console.log("优秀分数:", topScores); // [92,95]
console.log("平均分:", average); // 87.6
示例3:商品购物车
let cart = [
{id: 1, name: "手机", price: 2999, quantity: 1},
{id: 2, name: "耳机", price: 199, quantity: 2},
{id: 3, name: "充电宝", price: 149, quantity: 1}
];
// 1. 计算总价(不改变原数组)
let total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
console.log(`总价:${total}元`); // 总价:3495元
// 2. 查找商品(不改变原数组)
let phone = cart.find(item => item.name === "手机");
console.log(phone); // {id: 1, name: "手机", price: 2999, quantity: 1}
// 3. 删除商品(会改变原数组)
cart = cart.filter(item => item.name !== "耳机");
console.log(cart); // 耳机被删除
// 4. 修改商品数量(会改变原数组)
cart.forEach(item => {
if (item.name === "充电宝") {
item.quantity = 2;
}
});
示例4:学生成绩管理
let students = [
{name: "张三", score: 85},
{name: "李四", score: 92},
{name: "王五", score: 78},
{name: "赵六", score: 65}
];
// 1. 找出及格的学生(≥60)
let passed = students.filter(student => student.score >= 60);
console.log("及格的学生:", passed.map(s => s.name));
// 2. 计算平均分
let average = students.reduce((sum, student) => sum + student.score, 0) / students.length;
console.log(`平均分:${average.toFixed(1)}`);
// 3. 找出最高分
let topStudent = students.reduce((top, current) =>
current.score > top.score ? current : top
);
console.log(`最高分:${topStudent.name}(${topStudent.score}分)`);
// 4. 按成绩排序(不改变原数组)
let sorted = students.slice().sort((a, b) => b.score - a.score);
console.log("成绩排名:", sorted.map(s => `${s.name}: ${s.score}`));
示例5:数组去重
let numbers = [1, 2, 2, 3, 4, 4, 4, 5];
// 方法1:使用Set(ES6最简单,不改变原数组)
let unique1 = [...new Set(numbers)];
console.log(unique1); // [1, 2, 3, 4, 5]
// 方法2:使用filter(不改变原数组)
let unique2 = numbers.filter((value, index, array) => {
return array.indexOf(value) === index;
});
console.log(unique2); // [1, 2, 3, 4, 5]
// 方法3:使用reduce(不改变原数组)
let unique3 = numbers.reduce((unique, num) => {
if (!unique.includes(num)) {
unique.push(num);
}
return unique;
}, []);
console.log(unique3); // [1, 2, 3, 4, 5]
console.log(numbers); // [1,2,2,3,4,4,4,5](原数组不变)
九、最佳实践总结
1. 如何选择方法?
// 需要改变原数组的情况
let tasks = ["吃饭", "睡觉"];
tasks.push("打豆豆"); // ✅ 直接修改任务列表
// 需要保持原数组不变的情况
let originalData = [1, 2, 3, 4, 5];
let processedData = originalData.filter(x => x > 2); // ✅ 创建新数组
2. 防止意外修改原数组
let importantData = [10, 20, 30, 40];
// ❌ 危险:直接操作可能改变原数据
let sortedData = importantData.sort(); // 改变了importantData!
// ✅ 安全:先复制再操作
let sortedDataSafe = [...importantData].sort(); // 使用扩展运算符复制
// 或
let sortedDataSafe2 = importantData.slice().sort(); // 使用slice复制
console.log(importantData); // [10,20,30,40](不变)
console.log(sortedDataSafe); // [10,20,30,40]
3. 链式调用时注意
let numbers = [1, 2, 3, 4, 5];
// 可以链式调用的都是不改变原数组的方法
let result = numbers
.filter(x => x % 2 === 0) // 不改变原数组
.map(x => x * 2) // 不改变原数组
.slice(0, 2); // 不改变原数组
console.log(numbers); // [1,2,3,4,5](原数组不变)
console.log(result); // [4,8]
4. 性能考虑
// 1. 提前保存长度
for (let i = 0, len = arr.length; i < len; i++) {
// 比每次访问arr.length快
}
// 2. 使用Set快速去重
let unique = [...new Set(arr)]; // 最快
// 3. 避免在循环中修改数组长度
// ❌ 不好的写法
for (let i = 0; i < arr.length; i++) {
if (arr[i] < 0) {
arr.splice(i, 1); // 修改了数组长度
i--; // 需要调整索引
}
}
// ✅ 好的写法
arr = arr.filter(num => num >= 0);
十、总结口诀
🎯 改变原数组的方法(记住这八个):
push pop shift unshift
splice sort reverse fill
(推、弹、移头、加头、拼接、排序、反转、填充)
🎯 不改变原数组的方法(多数都友好):
slice concat join toString
map filter reduce forEach
indexOf includes find findIndex
some every flat flatMap
(切片、连接、转字符串、转字符串
映射、过滤、累积、遍历
查找位置、包含、找元素、找位置
一些满足、全都满足、压平、映射压平)
🎯 一句话总结:
- 会改变原数组:操作"队列"的方法(添加/删除/排序)
- 不会改变原数组:创建"新结果"的方法(查找/过滤/映射)
🎯 学习方法建议:
- 初学者:先掌握
push/pop、indexOf/includes、forEach、filter、map
- 常用组合:
filter().map()、map().reduce()
- 重要提醒:注意方法是否会改变原数组,避免意外bug
记住这个区别,能避免很多意想不到的bug!掌握数组方法是JavaScript编程的重要基础。