数组的Map方法详解

作用

map():创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。

语法

arr.map(callback(currentValue [, index [, array]]){ // Return element for new_array }[, thisArg])

  • callback:生成新数组元素的函数,该函数接收一至三个参数:
    • currentValue:数组中正在处理的当前元素。
    • index: 可选,数组中正在处理的当前元素的索引。
    • array: 可选, map 方法正在操作的数组。

thisArg: 可选,执行 callback 函数时值被用作 this

返回值:一个由原数组每个元素执行回调函数的结果组成的新数组。

  • map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。
  • callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。
  • callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。
  • map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)

因为 map 生成一个新数组,当你不打算使用返回的新数组却使用请用 forEach 或者 for-of 替代。

使用示例

求数组中每个元素的平方根

const numbers = [1, 4, 9];
const roots = numbers.map(Math.sqrt);
console.log(roots); // [1, 2, 3]

上述的代码在 map 中传入了一个 Math.sqrt 然后就计算出了 numbers 每个元素的平方根,那么它是如何实现的?
看如图所示,可以发现 Math.sqrt 实际上是一个函数,然后接收一个 number 类型的参数,在此示例中可以这么认为

const roots = numbers.map(function (item) {
  // 这里面就是 Math.sqrt 函数做的操作,它将返回每一个 item 的平方根
});

返回的数组元素中存在 undefined

const numbers = [1, 2, 3, 4, 5];
const filteredNumbers = numbers.map(function (num, index) {
  if (index < 3) {
    return num;
  }
});

console.log(filteredNumbers);

在 map 中改变了原数组

基础数据类型的数组,如代码与结果所示,基础类型的数组在修改 item 时并不会改变原数组。
是因为 map 方法处理数组元素的范围是在 callback 方法第一次调用之前就已经确定了。

const arr = [1, 5, 10, 15, 66, 200];

const newArr = arr.map(function (item) {
  if (item > 15) {
    item += 1
  }
  return item
});

console.log(arr);
console.log(newArr);

对象数组,如代码与结果所示,对象数组在修改 item 时会改变原数组

const arr = [
  { name: 'wfly', age: 18 },
  { name: 'fly', age: 8 },
  { name: 'fnn', age: 18 },
];

const newArr = arr.map(function (item) {
  if (item.name.includes('fly')) {
    item.age += 1
  }
  return item
});

console.log(arr);
console.log(newArr);

使用过程中直接改变原数组

  • map 方法处理数组元素的范围是在 callback 方法第一次调用之前就已经确定了。
  • 调用 map 方法之后 追加 的数组元素不会被 callback 访问。
  • 如果存在的数组元素改变了,那么传给 callback 的值是 map 访问该元素时的值。在 map 函数调用后但在访问该元素前,该元素被删除的话,则无法被访问到。
const arr = [3, 5, 10, 15, 66, 200];

const newArr = arr.map(function (item, index) {
  arr[index] = arr[index] + 10
  arr.push(999)
  console.log('当前 arr 的值:', arr);
  arr.unshift(111)
  return item
});

console.log(arr);
console.log(newArr);

如结果所示,会发现 newArr 输出的是 [3, 13, 23, 33, 43, 53],为什么会造成这种现象,
我们在示例代码中每一次 callback 的执行,都会将原数组的 arr 对象的 index+10,同时我们每一次执行 callback 都会在给原数组 push 一个元素以及 unshift 的一个元素
当然由于 push 是在尾部添加,它不会被 callback 所访问,但是 unshift 是在头部添加,会导致原数组之前的元素每执行一次 callback 都会向后移一项
由于 callbackitem,每次都是访问当前项的元素,而恰好 3 这个元素每次都是 +10 然后向后移一项,
所以得出结果 [3, 13, 23, 33, 43, 53]

所以上述的代码示例如果没有添加 unshift 去改变原数组的话,输出的结果就是 [3, 5, 10, 15, 66, 200]

map + parseInt 问题

["1", "2", "3"].map(parseInt); // [1, NaN, NaN]

如果看完第一个示例这个问题就很容易明白,parseInt 是一个函数,但是它接受的参数是两个,所以它不会输出 [1, 2, 3],
它在处理时实际上是 parseInt(1, 0),parseInt(2, 1),parseInt(3, 2),第一项参数是数组的 item,第二个参数是当前数组的索引

正确的处理方法应该如下

['1', '2', '3'].map(str => parseInt(str));
  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wflynn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值