JS Array.map 方法:底层原理、手写实现与实战细节

Array.prototype.map 是数组核心迭代方法,核心逻辑是遍历数组、执行回调转换元素、返回等长新数组(不改变原数组),空槽处理与 filter 有差异,需重点关注。

一、原生 map 核心特性(必记规则)

  1. 接收 2 个参数:callback(转换回调)、thisArg(回调中 this 指向,可选);
  2. 回调接收 3 个参数:currentValue(当前元素)、index(索引)、array(原数组);
  3. 返回与原数组长度相同的新数组,回调返回值作为新数组对应位置元素;
  4. 处理空槽:保留空槽结构(不执行回调,新数组对应位置仍为空槽);
  5. 不改变原数组,稀疏数组遍历后仍为稀疏数组(长度不变)。

二、手写实现 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;
};

三、核心细节解析

  1. 新数组初始化:用 new Array(len) 固定长度,确保新数组与原数组长度一致,空槽位置保留;
  2. 空槽处理i in arr 跳过空槽(不执行回调),新数组对应位置仍为空槽(原生特性),区别于 filter 的 “删除空槽”;
  3. this 绑定callback.call(thisArg) 确保回调中 this 指向正确(未传则为 undefined);
  4. 等长特性:无论回调返回什么,新数组长度必与原数组一致(空槽也占位置)。

四、使用示例(与原生 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 的核心区别

特性mapfilter
返回数组长度与原数组等长(保留空槽)小于等于原数组(删除空槽)
核心作用元素转换(如数值计算、格式处理)元素筛选(保留符合条件项)
回调返回值用途作为新数组元素值判断是否保留当前元素

六、避坑指南

  1. 空槽保留陷阱:稀疏数组 map 后仍为稀疏数组,若需密集数组,可后续处理:arr.map(...).filter(() => true)(删除空槽);
  2. 回调无返回值:回调未写 return 时,新数组对应位置为 undefined(而非空槽);
  3. 原数组修改风险:回调中若修改原数组元素(如 arr[i] = 10),会影响后续遍历(尽量避免);
  4. 引用类型元素:map 仅浅拷贝元素,若元素是对象 / 数组,新数组与原数组共享引用(修改会相互影响)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值