写点什么

forEach、map 和 for 循环

作者:编程江湖
  • 2021 年 12 月 31 日
  • 本文字数:1613 字

    阅读完需:约 5 分钟

forEach

没有返回值


var a = [1,2,3,4,5]var b = a.forEach((item) => { item = item * 2})console.log(b) // undefined复制代码
复制代码

无法中断执行

forEach 遍历过程中无法中断执行,如果希望符合某种条件时,就中断遍历,要使用for循环。

var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) { if (arr[i] === 2) break; console.log(arr[i]);}复制代码
复制代码

跳过空位

forEach()方法也会跳过数组的空位。

var a = [null, , undefined]for (let i = 0; i < a.length; i++) {    console.log('a', a[i]) // null undefined undefined}a.forEach(item => {    console.log('item', item) // null undefined});复制代码
复制代码

上面代码中,forEach()方法不会跳过undefinednull,但会跳过空位。而for循环不会跳过空位,会认为是undefined

改变数组情况

下面来看几个例子:

var a = [1,2,3,4,5]a.forEach((item) => {    item = item * 2})console.log(a) // [1,2,3,4,5]复制代码
复制代码

这里原数组并没有发生改变。

var a = [1,'1',{num:1},true] a.forEach((item, index, arr) => {    item = 2 }) console.log(a) // [1,'1',{num:1},true]复制代码
复制代码

这里修改 item 的值,依然没有修改原数组。

var a = [1,'1',{num:1},true] a.forEach((item, index, arr) => {     item.num = 2     item = 2}) console.log(a)  // [1,'1',{num:2},true]复制代码
复制代码

当修改数组中对象的某个属性时,发现属性改变了。其他值依旧没有改变。

为什么会这样呢?

这里就要引入(stack)内存和(heap)内存的概念了,前端培训对于 JS 中的基本数据类型,如String,Number,Boolean,Undefined,Null是存在于栈内存中的,在栈内存中储存变量名及相应的值。而Object,Array,Function存在于堆内存中,在堆内存中储存变量名及引用位置。

  • 在第一个例子中,为什么直接修改 item 无法修改原数组呢,因为 item 的值并不是相应的原数组中的值,而是重新建立的一个新变量,值和原数组相同。因此,如果 item 是基础数据类型,那么并不会改变数组里面的值,如果是引用类型,那么 item 和数组里面的值是指向同一内存地址,则都会被改变。

  • 在第二个例子中,数组中的对象的值也没有改变,是因为新创建的变量和原数组中的对象虽然指向同一个地址,但改变的是新变量的值,也就是重新赋值,即新对象的值为 2,原数组中的对象还是{num:1}

  • 在第三个例子中,由于对象是引用类型,新对象和旧对象指向的都是同一个地址,所以新对象把 num 变成了 2,原数组中的对象也改变了。

var a = [1,2,3,4,5] a.forEach((item, index, arr) => {     arr[index] = item * 2 }) console.log(a)  // [2,4,6,8,10]复制代码
复制代码

在回调函数里改变 arr 的值,原数组改变了。

这个例子和例三其实同理,参数中的 arr 也只是原数组的一个拷贝,但是 arr 是引用类型。如果修改数组中的某一项则原数组也改变因为指向同一引用地址,而如果给参数 arr 赋其他值,那就是重新赋值,则原数组不变。如下:

var a = [1,2,3,4,5] a.forEach((item, index, arr) => {     arr = 2}) console.log(a)  // [1,2,3,4,5]复制代码
复制代码

map

有返回值

返回一个经过处理后的新数组,但不改变原数组的值。

var a = [1,2,3,4,5]var b = a.map((item) => {    return item = item * 2})console.log(a)  // [1,2,3,4,5]console.log(b)  // [2,4,6,8,10]复制代码
复制代码

无法中断执行

同 forEach,无法中断执行

跳过空位

同 forEach,会跳过空位

改变数组情况

map 中可改变原数组的情况和原理与 forEach 相同

性能对比

  1. for 循环当然是最简单的,因为它没有任何额外的函数调用栈和上下文;

  2. forEach 其次,因为它其实比我们想象得要复杂一些,它的函数签名实际上是array.forEach(function(currentValue, index, arr), thisValue)它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能

  3. map 最慢,因为它的返回值是一个等长的全新的数组,数组创建和赋值产生的性能开销很大。

用户头像

编程江湖

关注

IT技术分享 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
forEach、map和for循环