共计 2032 个字符,预计需要花费 6 分钟才能阅读完成。
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()办法不会跳过 undefined 和 null,但会跳过空位。而 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 最慢,因为它的返回值是一个等长的全新的数组,数组创立和赋值产生的性能开销很大。