标准答案

  1. map 返回一个新数组,不应该修改原数组。
  2. callback 接收当前值、索引和原数组。
  3. 需要支持 thisArg,让回调里的 this 指向指定对象。
  4. 稀疏数组里不存在的索引不会执行 callback。
  5. 实现前要检查调用者不是 null 或 undefined,callback 必须是函数。

题目解析

手写 map 不是简单 for 循环 push。更接近原生行为的实现要考虑 thisArg、稀疏数组和基础参数校验。

结果数组的长度应该和原数组一致。对于稀疏数组,空位仍然是空位,不应该因为 push 变成连续数组。

这道题适合体现对数组迭代方法共同模式的理解:不改变原数组,按索引访问,回调参数一致,返回新集合。

代码示例

下面的实现保留数组长度,并跳过不存在的索引。

JavaScript
function map(array, callback, thisArg) {
  if (array == null) {
    throw new TypeError('array is null or undefined')
  }

  if (typeof callback !== 'function') {
    throw new TypeError('callback must be a function')
  }

  const source = Object(array)
  const length = source.length >>> 0
  const result = new Array(length)

  for (let index = 0; index < length; index += 1) {
    if (index in source) {
      result[index] = callback.call(thisArg, source[index], index, source)
    }
  }

  return result
}

常见误区

  • 用 push 生成结果,导致稀疏数组空位行为和原生 map 不一致。
  • 忘记传 index 和原数组,回调能力不完整。
  • 忽略 thisArg,包装对象方法时上下文不符合预期。

作者信息