引言

数组是JavaScript中最重要和常用的数据结构。本文将全面详细介绍JavaScript数组的方法,包含详细的参数说明、返回值解释和实际应用场景,帮助你彻底掌握数组操作。

本篇文章,对我所整理的所有方法都有详细讲解,篇幅较长(万字)。如想快速查阅数组方法可查看我的另一篇文章JavaScript 数组方法指南(快速查阅版)

一、修改原数组的方法详解

1. push() 方法

        ​​作用​​:在数组末尾添加一个或多个元素

        语法​​:

arr.push(element1, ..., elementN)

        参数​​:

  • element1, ..., elementN:要添加到数组末尾的元素

​        返回值​​:数组的新长度

        示例​​:

const fruits = ['apple', 'banana'];
const newLength = fruits.push('orange', 'grape');
console.log(fruits); // ['apple', 'banana', 'orange', 'grape']
console.log(newLength); // 4

2. pop() 方法

        ​​作用​​:删除数组的最后一个元素

​        语法​​:

arr.pop()

         返回值​​:被删除的元素,如果数组为空则返回undefined

​        示例​​:

const fruits = ['apple', 'banana', 'orange'];
const lastFruit = fruits.pop();
console.log(fruits); // ['apple', 'banana']
console.log(lastFruit); // 'orange'

3. unshift() 方法

​        作用​​:在数组开头添加一个或多个元素

​        语法​​:

arr.unshift(element1, ..., elementN)

        示例​​:

const fruits = ['banana', 'orange'];
fruits.unshift('apple');
console.log(fruits); // ['apple', 'banana', 'orange']

4. shift() 方法

​        作用​​:删除数组的第一个元素

        ​​语法​​:

arr.shift()

        示例​​:

const fruits = ['apple', 'banana', 'orange'];
const firstFruit = fruits.shift();
console.log(fruits); // ['banana', 'orange']
console.log(firstFruit); // 'apple'

5. splice() 方法

​        作用​​:通过删除或替换现有元素或者添加新元素来修改数组

        ​​语法​​:

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

        参数​​:

  • start:修改开始的位置
  • deleteCount:要删除的元素个数

  • item1, item2, ...:要添加进数组的元素

        ​​示例​​:

const months = ['Jan', 'March', 'April', 'June'];

// 在索引1的位置添加一个元素
months.splice(1, 0, 'Feb');
console.log(months); // ['Jan', 'Feb', 'March', 'April', 'June']

// 替换索引4位置的元素
months.splice(4, 1, 'May');
console.log(months); // ['Jan', 'Feb', 'March', 'April', 'May']

二、不修改原数组的方法详解

 6. concat() 方法

        ​​作用​​:合并两个或多个数组

​        示例​​:

const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];

const result = arr1.concat(arr2, arr3);
console.log(result); // [1, 2, 3, 4, 5, 6]

7. slice() 方法

        ​​作用​​:返回数组的浅拷贝 portion

​        语法​​:

array.slice(startIndex[, endIndex])
  • 参数说明

    • startIndex:必需,提取的起始位置(包含该位置元素)
      • 若为正数:从数组开头计数(0 表示第一个元素)
      • 若为负数:从数组末尾计数(-1 表示最后一个元素)
    • endIndex:可选,提取的结束位置(不包含该位置元素)
      • 若省略:提取从 startIndex 到数组末尾的所有元素
      • 若为负数:从数组末尾计数

        示例​​:

const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

console.log(animals.slice(2)); // ['camel', 'duck', 'elephant']
console.log(animals.slice(2, 4)); // ['camel', 'duck']
console.log(animals.slice(1, 5)); // ['bison', 'camel', 'duck', 'elephant']

8. join() 方法

​        作用​​:将数组所有元素连接成字符串

​        示例​​:

const elements = ['Fire', 'Air', 'Water'];

console.log(elements.join()); // "Fire,Air,Water"
console.log(elements.join('')); // "FireAirWater"
console.log(elements.join('-')); // "Fire-Air-Water"

三、搜索和查找方法详解

9. indexOf() 和 lastIndexOf()

        ​​作用​​:查找元素的索引位

  • indexOf():从开头开始查找,返回指定元素 / 字符第一次出现的索引;若不存在,返回 -1
  • lastIndexOf():从末尾开始查找,返回指定元素 / 字符最后一次出现的索引;若不存在,返回 -1

        参数说明:

         第一个参数为查找元素(必须),第二个为开始位置(可选)                                          

​        示例​:

const array = [2, 5, 9, 2];

console.log(array.indexOf(2)); // 0
console.log(array.indexOf(7)); // -1
console.log(array.indexOf(2, 2)); // 3
console.log(array.lastIndexOf(2)); // 3

10. includes() 方法

​        作用​​:判断数组是否包含某个元素

        语法:

array.includes(searchValue[, fromIndex])
  • 参数说明

    • searchValue:必需,要查找的元素。
    • fromIndex:可选,开始查找的起始索引(默认值为 0)。
      • 若为正数:从该索引处开始向后查找(包含该索引)。
      • 若为负数:表示从数组末尾开始计算的偏移量(例如 -1 表示从最后一个元素开始查找)。
      • 若偏移后的值小于 0,则从数组开头开始查找。

​        示例​​:

const array = [1, 2, 3];

console.log(array.includes(2)); // true
console.log(array.includes(4)); // false
console.log(array.includes(3, 3)); // false

11. find() 方法

​        作用​​:用于查找数组中满足指定条件的第一个元素,返回该元素;如果没有找到符合条件的元素,则返回 undefined

        语法:

array.find(callback(element[, index[, array]])[, thisArg])
  • 参数说明

    • callback:必需,用于测试每个元素的函数,返回 true 时表示找到符合条件的元素,停止查找。
      • element:当前正在处理的数组元素。
      • index:可选,当前元素的索引。
      • array:可选,调用 find() 方法的数组本身。
    • thisArg:可选,执行 callback 时用作 this 的值。

         示例​​:

const users = [
  { id: 1, name: 'Alice', age: 17 },
  { id: 2, name: 'Bob', age: 19 },
  { id: 3, name: 'Charlie', age: 21 }
];

// 查找第一个成年用户(age ≥ 18)
const adultUser = users.find(user => user.age >= 18);
console.log(adultUser); // { id: 2, name: 'Bob', age: 19 }

// 查找 id 为 3 的用户
const userWithId3 = users.find((user, index) => {
  console.log(`正在检查索引 ${index} 的元素`); // 会打印 0、1、2
  return user.id === 3;
});
console.log(userWithId3); // { id: 3, name: 'Charlie', age: 21 }

// 查找不存在的元素(返回 undefined)
const userWithId10 = users.find(user => user.id === 10);
console.log(userWithId10); // undefined

12.findIndex()方法

        作用​​:用于查找数组中满足指定条件的第一个元素的索引,返回该索引;如果没有找到符合条件的元素,则返回 -1

        语法:

array.findIndex(callback(element[, index[, array]])[, thisArg])
  • 参数说明:与 find() 完全相同,区别在于返回值是 “索引” 而非 “元素”。

         示例​​:

const numbers = [5, 12, 8, 130, 44];

// 查找第一个大于 10 的元素的索引
const firstLargeIndex = numbers.findIndex(num => num > 10);
console.log(firstLargeIndex); // 1(元素 12 的索引是 1)

// 结合对象数组使用
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

// 查找 name 为 'Bob' 的用户的索引
const bobIndex = users.findIndex(user => user.name === 'Bob');
console.log(bobIndex); // 1

// 查找不存在的元素(返回 -1)
const mikeIndex = users.findIndex(user => user.name === 'Mike');
console.log(mikeIndex); // -1

四、迭代方法详解

12. forEach() 方法

​        作用​​:用于遍历数组中的每个元素,并对每个元素执行指定的回调函数。没有返回值(返回 undefined),主要用于替代传统的 for 循环进行数组遍历。   

         语法:

array.forEach(callback(element[, index[, array]])[, thisArg])
  • 参数说明

    • callback:必需,对每个元素执行的函数。
      • element:当前正在处理的数组元素。
      • index:可选,当前元素的索引。
      • array:可选,调用 forEach() 方法的数组本身。
    • thisArg:可选,执行 callback 时用作 this 的值。

         示例​​:

const fruits = ['apple', 'banana', 'cherry'];

// 基本用法:遍历数组并打印每个元素
fruits.forEach(fruit => {
  console.log(fruit);
});
// 输出:
// apple
// banana
// cherry

// 带索引的遍历
fruits.forEach((fruit, index) => {
  console.log(`索引 ${index} 的元素是:${fruit}`);
});
// 输出:
// 索引 0 的元素是:apple
// 索引 1 的元素是:banana
// 索引 2 的元素是:cherry

// 操作数组元素(注意:无法直接修改原数组的元素引用,需通过索引修改)
const numbers = [1, 2, 3];
numbers.forEach((num, index, arr) => {
  arr[index] = num * 2; // 通过索引修改原数组元素
});
console.log(numbers); // [2, 4, 6]

// 注意:forEach 无法通过 break 或 return 终止循环
const nums = [1, 2, 3, 4, 5];
nums.forEach(num => {
  if (num > 3) return; // 仅跳过当前迭代,不会终止整个循环
  console.log(num);
});
// 输出:1, 2, 3(4和5被跳过,但循环仍执行完所有元素)

13. map() 方法

 作用​​:对数组中的每个元素执行指定的回调函数,将每个元素处理后的结果组成一个新数组并返回,不改变原数组。常用于对数组元素进行批量转换或处理。

         语法:

array.map(callback(element[, index[, array]])[, thisArg])
  • 参数说明

    • callback:必需,对每个元素执行的函数,返回处理后的结果(该结果会被加入新数组)。
      • element:当前正在处理的数组元素。
      • index:可选,当前元素的索引。
      • array:可选,调用 map() 方法的原数组。
    • thisArg:可选,执行 callback 时用作 this 的值。

         示例​​:

const numbers = [1, 2, 3, 4, 5];

// 基本用法:将每个元素乘以 2
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5](原数组不变)

// 处理对象数组:提取对象的某个属性
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];
const userNames = users.map(user => user.name);
console.log(userNames); // ['Alice', 'Bob', 'Charlie']

// 结合索引进行处理
const indexedNumbers = numbers.map((num, index) => {
  return `第${index + 1}个数字:${num}`;
});
console.log(indexedNumbers); 
// ['第1个数字:1', '第2个数字:2', '第3个数字:3', '第4个数字:4', '第5个数字:5']

// 注意:map 会为每个元素创建新值,即使返回原元素
const sameElements = numbers.map(num => num);
console.log(sameElements); // [1, 2, 3, 4, 5](新数组,与原数组元素相同)

14. filter() 方法

​        作用​​:创建一个新数组,包含原数组中所有满足指定条件(通过回调函数测试)的元素,不改变原数组。常用于从数组中筛选符合条件的元素。        

         语法:

array.filter(callback(element[, index[, array]])[, thisArg])
  • 参数说明

    • callback:必需,用于测试每个元素的函数,返回 true 则保留该元素,false 则排除。
      • element:当前正在处理的数组元素。
      • index:可选,当前元素的索引。
      • array:可选,调用 filter() 方法的原数组。
    • thisArg:可选,执行 callback 时用作 this 的值。
const numbers = [10, 23, 5, 8, 37, 14];

// 基本用法:筛选出大于 20 的数字
const largeNumbers = numbers.filter(num => num > 20);
console.log(largeNumbers); // [23, 37]
console.log(numbers); // [10, 23, 5, 8, 37, 14](原数组不变)

// 筛选对象数组:保留成年用户
const users = [
  { name: 'Alice', age: 17 },
  { name: 'Bob', age: 22 },
  { name: 'Charlie', age: 19 },
  { name: 'Diana', age: 16 }
];
const adults = users.filter(user => user.age >= 18);
console.log(adults); 
// 输出:[{ name: 'Bob', age: 22 }, { name: 'Charlie', age: 19 }]

// 结合索引筛选:排除索引为 1 的元素
const filteredByIndex = numbers.filter((num, index) => index !== 1);
console.log(filteredByIndex); // [10, 5, 8, 37, 14]

// 筛选非空字符串
const strs = ['', 'hello', ' ', 'world', null];
const nonEmptyStrs = strs.filter(str => typeof str === 'string' && str.trim() !== '');
console.log(nonEmptyStrs); // ['hello', 'world']

15. reduce() 方法

​        作用​​:对数组中的每个元素执行回调函数,将数组 “缩减” 为单个值(可以是数字、对象、数组等)。常用于求和、求积、统计、分组、扁平化数组等复杂操作。​​        

         语法:

array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
  • 参数说明

    • callback:必需,用于处理每个元素的函数,返回值会作为下一次调用的 accumulator
      • accumulator:累计器,存储上一次回调的返回值(或初始值 initialValue)。
      • currentValue:当前正在处理的数组元素。
      • index:可选,当前元素的索引。
      • array:可选,调用 reduce() 方法的原数组。
    • initialValue:可选,作为第一次调用 callback 时的 accumulator 初始值。若不提供,会将数组的第一个元素作为初始 accumulator,并从第二个元素开始遍历。
const numbers = [1, 2, 3, 4, 5];

// 1. 求和(提供初始值)
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15(0 + 1 + 2 + 3 + 4 + 5)

// 2. 求积(不提供初始值,默认用第一个元素作为初始 accumulator)
const product = numbers.reduce((acc, curr) => acc * curr);
console.log(product); // 120(1 * 2 * 3 * 4 * 5)

// 3. 统计元素出现次数(返回对象)
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const countFruits = fruits.reduce((acc, curr) => {
  acc[curr] = (acc[curr] || 0) + 1; // 若属性不存在则初始化为 0,再 +1
  return acc;
}, {}); // 初始值为空对象
console.log(countFruits); // { apple: 3, banana: 2, orange: 1 }

// 4. 数组分组(按属性分组)
const users = [
  { name: 'Alice', age: 20 },
  { name: 'Bob', age: 18 },
  { name: 'Charlie', age: 20 },
  { name: 'Diana', age: 18 }
];
const groupedByAge = users.reduce((acc, curr) => {
  const key = curr.age;
  if (!acc[key]) {
    acc[key] = []; // 若分组不存在则初始化空数组
  }
  acc[key].push(curr);
  return acc;
}, {});
console.log(groupedByAge);
// {
//   18: [{ name: 'Bob', age: 18 }, { name: 'Diana', age: 18 }],
//   20: [{ name: 'Alice', age: 20 }, { name: 'Charlie', age: 20 }]
// }

// 5. 扁平化二维数组
const nestedArray = [[1, 2], [3, 4], [5, 6]];
const flatArray = nestedArray.reduce((acc, curr) => acc.concat(curr), []);
console.log(flatArray); // [1, 2, 3, 4, 5, 6]

注意:若数组为空且未提供 initialValuereduce() 会抛出错误;建议尽量提供 initialValue,避免逻辑混乱。

五、ES6+ 新方法详解

16. flat() 和 flatMap()

​        作用​​:数组扁平化处理

​        示例​​:

const arr1 = [1, 2, [3, 4]];
console.log(arr1.flat()); // [1, 2, 3, 4]

const arr2 = [1, 2, [3, 4, [5, 6]]];
console.log(arr2.flat(2)); // [1, 2, 3, 4, 5, 6]

// flatMap相当于map之后执行flat(1)
const arr3 = [1, 2, 3];
console.log(arr3.flatMap(x => [x * 2])); // [2, 4, 6]

17. Array.from() 方法

        ​​作用​​:将类数组对象(具有 length 属性的对象)或可迭代对象(如字符串、Set、Map 等)转换为真正的数组。返回一个新的数组实例,不会修改原对象。

        语法:

Array.from(arrayLike[, mapFn[, thisArg]])
  • 参数说明

    • arrayLike:必需,要转换为数组的类数组对象或可迭代对象(如 arguments、DOM 集合、字符串、Set 等)。
    • mapFn:可选,映射函数,对转换后的数组中的每个元素进行处理,类似于 map() 方法的回调函数。
    • thisArg:可选,执行 mapFn 时用作 this 的值。
// 1. 转换类数组对象(如 arguments)
function sum() {
  const args = Array.from(arguments); // 将 arguments 转换为数组
  return args.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

// 2. 转换字符串(字符串是可迭代对象)
const str = 'hello';
const strArray = Array.from(str);
console.log(strArray); // ['h', 'e', 'l', 'l', 'o']

// 3. 转换 Set(Set 是可迭代对象)
const set = new Set(['a', 'b', 'c']);
const setArray = Array.from(set);
console.log(setArray); // ['a', 'b', 'c']

// 4. 使用映射函数处理元素
const numbers = [1, 2, 3];
// 转换为数组并将每个元素乘以 2(等效于 Array.from(numbers).map(n => n*2))
const doubled = Array.from(numbers, n => n * 2);
console.log(doubled); // [2, 4, 6]

// 5. 生成指定长度的数组并初始化
const length = 5;
const initializedArray = Array.from({ length }, (_, index) => index + 1);
console.log(initializedArray); // [1, 2, 3, 4, 5]

// 6. 转换 DOM 集合(如 NodeList)
// 假设页面中有多个 <div> 元素
// const divs = document.getElementsByTagName('div');
// const divArray = Array.from(divs); // 将 NodeList 转换为数组,可使用数组方法

Array.from() 是处理非数组对象(但具有数组特征)的常用方法,尤其在需要使用数组原生方法(如 mapfilter)时非常实用。

18. Array.of() 方法

​        作用​​:创建一个新的数组实例,将传入的所有参数作为数组元素,无论参数的数量或类型如何。与 Array 构造函数不同,Array.of() 不会因单个数字参数而改变行为(即不会将数字视为数组长度)。

​        示例​​:

// 1. 基本用法:传入多个参数
const arr1 = Array.of(1, 2, 3, 4);
console.log(arr1); // [1, 2, 3, 4]

// 2. 传入单个参数(与 Array 构造函数对比)
const arr2 = Array.of(5);
console.log(arr2); // [5](参数作为元素)

const arr3 = new Array(5);
console.log(arr3); // [empty × 5](参数作为长度,创建空数组)

// 3. 传入不同类型的参数
const arr4 = Array.of('a', 10, true, { name: 'test' });
console.log(arr4); // ['a', 10, true, { name: 'test' }]

// 4. 传入零个参数(返回空数组)
const arr5 = Array.of();
console.log(arr5); // []

六、实际应用场景

        场景1:数据处理和转换

// 从API获取的数据处理
const apiData = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 25 }
];

// 获取所有年龄为25的用户名
const names = apiData
  .filter(user => user.age === 25)
  .map(user => user.name);

console.log(names); // ['Alice', 'Charlie']

        场景2:购物车计算

const cart = [
  { name: 'iPhone', price: 999, quantity: 1 },
  { name: 'Case', price: 25, quantity: 2 },
  { name: 'Charger', price: 49, quantity: 1 }
];

// 计算总价
const total = cart.reduce((sum, item) => {
  return sum + (item.price * item.quantity);
}, 0);

console.log(total); // 1098

        场景3:数据统计和分析

const sales = [120, 150, 80, 200, 95, 175];

// 统计分析
const stats = {
  total: sales.reduce((a, b) => a + b, 0),
  average: sales.reduce((a, b) => a + b, 0) / sales.length,
  max: Math.max(...sales),
  min: Math.min(...sales),
  aboveAverage: sales.filter(amount => amount > 100)
};

console.log(stats);

七、性能考虑和最佳实践

1. 选择合适的方法

  • 需要修改原数组时使用:push()pop()splice()

  • 需要返回新数组时使用:map()filter()slice()

  • 大数据集考虑性能:for循环可能比forEach更快

2. 避免常见的陷阱

// ❌ 错误:在forEach中修改原数组可能导致意外行为
array.forEach((item, index) => {
  if (item === 0) {
    array.splice(index, 1); // 危险操作!
  }
});

// ✅ 正确:使用filter创建新数组
const newArray = array.filter(item => item !== 0);

总结

JavaScript数组提供了丰富的方法来满足各种数据处理需求。掌握这些方法能够显著提高开发效率和代码质量。建议在实际项目中多加练习,逐步掌握每个方法的适用场景和最佳实践。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐