Array.prototype.map 是数组核心迭代方法,核心逻辑是遍历数组、执行回调转换元素、返回等长新数组(不改变原数组),空槽处理与 filter 有差异,需重点关注。
一、原生 map 核心特性(必记规则)
- 接收 2 个参数:
callback(转换回调)、thisArg(回调中this指向,可选); - 回调接收 3 个参数:
currentValue(当前元素)、index(索引)、array(原数组); - 返回与原数组长度相同的新数组,回调返回值作为新数组对应位置元素;
- 处理空槽:保留空槽结构(不执行回调,新数组对应位置仍为空槽);
- 不改变原数组,稀疏数组遍历后仍为稀疏数组(长度不变)。
二、手写实现 map(还原原生逻辑)
Array.prototype.myMap = function (callback, thisArg) {
// 1. 校验参数:callback 必须是函数
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`);
}
// 2. 定义变量:原数组、新数组(长度与原数组一致)、原数组长度
const arr = this;
const len = arr.length;
const result = new Array(len); // 关键:初始化新数组长度,保留空槽位置
// 3. 遍历原数组,仅处理已初始化的索引(空槽跳过回调)
for (let i = 0; i < len; i++) {
if (i in arr) { // 跳过空槽,不执行回调
// 4. 执行回调,绑定 this,传递 3 个参数,接收转换后的值
const transformedVal = callback.call(thisArg, arr[i], i, arr);
// 5. 赋值到新数组对应索引
result[i] = transformedVal;
}
// 空槽:不执行回调,result[i] 保持初始化时的空槽状态
}
// 6. 返回新数组
return result;
};
三、核心细节解析
- 新数组初始化:用
new Array(len)固定长度,确保新数组与原数组长度一致,空槽位置保留; - 空槽处理:
i in arr跳过空槽(不执行回调),新数组对应位置仍为空槽(原生特性),区别于filter的 “删除空槽”; - this 绑定:
callback.call(thisArg)确保回调中this指向正确(未传则为undefined); - 等长特性:无论回调返回什么,新数组长度必与原数组一致(空槽也占位置)。
四、使用示例(与原生 map 对比)
const arr = [1, , 3, undefined, null]; // 索引1是空槽
const thisArg = { base: 2 };
// 原生 map
const nativeRes = arr.map(function (item, index) {
console.log(item); // 打印 1、3、undefined、null(空槽跳过回调)
return item * this.base; // this 指向 thisArg
}, thisArg);
console.log(nativeRes); // [2, , 6, NaN, 0](空槽保留,undefined*2=NaN)
// 手写 myMap
const myRes = arr.myMap(function (item, index) {
console.log(item); // 同上,空槽跳过
return item * this.base;
}, thisArg);
console.log(myRes); // [2, , 6, NaN, 0](与原生完全一致)
五、map 与 filter 的核心区别
| 特性 | map | filter |
|---|---|---|
| 返回数组长度 | 与原数组等长(保留空槽) | 小于等于原数组(删除空槽) |
| 核心作用 | 元素转换(如数值计算、格式处理) | 元素筛选(保留符合条件项) |
| 回调返回值用途 | 作为新数组元素值 | 判断是否保留当前元素 |
六、避坑指南
- 空槽保留陷阱:稀疏数组 map 后仍为稀疏数组,若需密集数组,可后续处理:
arr.map(...).filter(() => true)(删除空槽); - 回调无返回值:回调未写
return时,新数组对应位置为undefined(而非空槽); - 原数组修改风险:回调中若修改原数组元素(如
arr[i] = 10),会影响后续遍历(尽量避免); - 引用类型元素:map 仅浅拷贝元素,若元素是对象 / 数组,新数组与原数组共享引用(修改会相互影响)。

被折叠的 条评论
为什么被折叠?



