标准答案
- map 的核心是创建一个和原数组 length 相同的新数组,遍历存在的索引,把 callback(value, index, array) 的返回值写到对应位置。
- filter 的核心是遍历存在的索引,回调返回真值时,把当前元素 push 到结果数组。
- reduce 的核心是维护 accumulator。如果提供 initialValue,就从索引 0 开始;如果没有提供,就找到第一个存在的元素作为初始 accumulator。
- 空数组没有 initialValue 时,reduce 要抛 TypeError。手写时还要注意稀疏数组空洞、thisArg、回调参数顺序和不直接修改原数组。
题目解析
手写数组方法常见失分点不是主流程,而是边界:稀疏数组的空洞不应触发回调,reduce 没有初始值时要找第一个实际存在的元素。
map 返回等长数组,filter 返回长度不固定的新数组,reduce 返回累计结果。三者的返回值语义不同,不能混用。
真实规范还会处理 this 为 null/undefined、callback 是否函数、length 快照、类数组对象等细节。面试核心版至少要把回调参数、thisArg、空洞和 reduce 初始值说清。
代码示例
下面示例覆盖 map、filter、reduce 的核心逻辑和 reduce 初始值边界。
JavaScript
function myMap(array, callback, thisArg) {
const result = new Array(array.length)
for (let index = 0; index < array.length; index += 1) {
if (index in array) {
result[index] = callback.call(thisArg, array[index], index, array)
}
}
return result
}
function myFilter(array, callback, thisArg) {
const result = []
for (let index = 0; index < array.length; index += 1) {
if (index in array && callback.call(thisArg, array[index], index, array)) {
result.push(array[index])
}
}
return result
}
function myReduce(array, callback, initialValue) {
let index = 0
let accumulator = initialValue
if (arguments.length < 3) {
while (index < array.length && !(index in array)) {
index += 1
}
if (index >= array.length) {
throw new TypeError('Reduce of empty array with no initial value')
}
accumulator = array[index]
index += 1
}
for (; index < array.length; index += 1) {
if (index in array) {
accumulator = callback(accumulator, array[index], index, array)
}
}
return accumulator
}常见误区
- reduce 空数组无初始值时返回 undefined,而不是抛错。
- map/filter 遍历稀疏数组空洞并调用回调。
- 忘记 thisArg 和回调参数顺序。