1. 核心概念 (Core Concept)
JavaScript 的 Array.prototype 上提供了大量内置方法,用于遍历、转换和操作数组。面试中常考的方法主要围绕其功能、返回值、是否改变原数组 (mutability) 以及与其它方法的对比。
关键方法分类:
- 迭代方法:
forEach,map,filter,reduce,some,every - 修改原数组 (Mutator methods):
push,pop,shift,unshift,splice,sort,reverse - 返回新数组 (Non-mutating methods):
concat,slice,map,filter,reduce
2. 为什么需要深入理解它们? (The "Why")
- 编写高效、简洁的代码: 熟练运用这些高阶函数,可以替代复杂的
for循环,使代码更具可读性和表现力。 - 避免副作用: 清晰地知道哪些方法会修改原数组,是防止程序出现意外状态变更的关键,尤其是在函数式编程和状态管理(如 React/Redux)中。
- 考察基础编程能力: 对这些常用方法的熟练程度和细节的掌握,是衡量一个开发者 JS 基础是否扎实的常用指标。例如,能否手动实现
map或reduce。
3. API 与用法 (API & Usage)
map()
- 核心功能: 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
- 返回值: 一个新的、长度与原数组相同的新数组。
- 是否改变原数组: 否。
javascript
const numbers = [1, 4, 9];
const doubles = numbers.map(num => num * 2);
console.log(doubles); // 输出: [2, 8, 18]
console.log(numbers); // 输出: [1, 4, 9] (原数组不变)filter()
- 核心功能: 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
- 返回值: 一个新的、可能比原数组短的新数组。
- 是否改变原数组: 否。
javascript
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction'];
const result = words.filter(word => word.length > 6);
console.log(result); // 输出: ["exuberant", "destruction"]reduce()
- 核心功能: 对数组中的每个元素执行一个 "reducer" 函数(升序执行),将其结果汇总为单个返回值。
- 返回值: 函数累计处理的结果。
API: arr.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue) - accumulator (累加器): 累计回调的返回值; 它是上一次调用回调时返回的累积值,或 initialValue。 - initialValue (可选): 作为第一次调用 callback 函数时的第一个参数的值。
javascript
const array = [1, 2, 3, 4];
const initialValue = 0;
const sum = array.reduce(
(accumulator, currentValue) => accumulator + currentValue,
initialValue
);
console.log(sum); // 输出: 10splice()
- 核心功能: 通过删除或替换现有元素或者原地添加新的元素来修改数组。
- 返回值: 一个由被删除的元素组成的新数组。如果未删除任何元素,则返回空数组。
- 是否改变原数组: 是。
javascript
const months = ['Jan', 'March', 'April', 'June'];
// 在索引 1 的位置,删除 0 个元素,插入 'Feb'
const removed = months.splice(1, 0, 'Feb');
console.log(months); // 输出: ["Jan", "Feb", "March", "April", "June"]
console.log(removed); // 输出: [] (没有元素被删除)
// 从索引 3 的位置,删除 1 个元素
const removedItem = months.splice(3, 1);
console.log(months); // 输出: ["Jan", "Feb", "March", "June"]
console.log(removedItem); // 输出: ["April"]4. 关键注意事项 (Key Considerations)
mapvsforEach:- 返回值:
map返回一个新数组,forEach返回undefined。 - 用途: 当你需要转换数据并得到一个新数组时用
map。当你只需要对数组中每个元素执行一个操作(如打印、调用 API)而不需要返回值时用forEach。 - 链式调用:
map可以进行链式调用 (arr.map(...).filter(...)),forEach不行。
- 返回值:
reduce的initialValue:- 提供
initialValue:reduce会从数组的第一个元素开始执行回调,accumulator的初始值就是initialValue。 - 不提供
initialValue:reduce会从数组的第二个元素开始执行回调,accumulator的初始值是数组的第一个元素,currentValue是第二个元素。对空数组调用reduce且没有initialValue会抛出TypeError。
- 提供
可变性 (Mutability) 是核心考点:
- 修改原数组:
push,pop,shift,unshift,splice,sort,reverse。在 React 等场景下应避免直接对 state 数组使用这些方法。 - 不修改原数组:
map,filter,reduce,slice,concat。这些是创建新状态的首选方法。 slicevssplice:slice返回数组的浅拷贝片段,不修改原数组。splice修改原数组,用于添加/删除元素。名称相似但功能和副作用完全不同。
- 修改原数组:
稀疏数组的处理:
map,forEach,filter等迭代方法会跳过稀疏数组中的空位。reduce也会跳过空位(除非提供了initialValue)。
