需求:想要给页面中的button加点击事件 然后输出索引值
以下代码实现不了,原因是当点击事件执行的时候 循环已经结束 此时i=3 执行点击事件代码 其中没有i变量 从全局变量找此时i=3。所以每次输出都是3
var buttons = document.querySelectorAll('button') // Nodelist 类数组集合
for(var i=0;i<buttons.length;i++){
buttons[i].onclick = function(){
console.log(`当前点击索引:${i}`)
}
}
解决的办法有很多,我们可以通过let、闭包等等。但是今天通过这个例子讨论for和forEach的区别。我们用forEach 却可以解决。
var buttons = document.querySelectorAll('button') // Nodelist 类数组集合
buttons.forEach((item,index)=>{
item.onclick = function(){
console.log(`当前点击索引:${index}`)
}
})
为什么?
for循环在最开始执行循环的时候,会建立一个循环变量i,这个i属于window的,因为for没有作用域。之后每次循环都是操作这个变量,也就是说它是对一个循环变量在重复的赋值,因此 i 在最后只会存储一个值。
而forEach()虽然变量名没变,但是实际上每次循环在回调函数中都会创建一个独立不同的变量(因为回调函数有函数作用域),而存储的数值自然也是不同的数值,因此相互之间不会影响。
补充:从性能考虑,也有区别
有的说for循环快,有的说forEach快。
var arr=new Array(100000000)
console.time('BB')
arr.forEach(item=>{
})
console.timeEnd('BB')
console.time('AA')
var i;
for(i=0;i<arr.length;i++){
}
console.timeEnd('AA')
image.png
如果只是循环的话,很显然for要快于forEach,将近10倍。
再看另一个数据
var arr=new Array(100000000)
console.time('forEach')
arr.forEach(item=>{
let b =item
b =item
b =item
})
console.timeEnd('forEach')
console.time('for')
var i;
for(i=0;i<arr.length;i++){
let a = arr[i]
a=arr[i]
a=arr[i]
}
console.timeEnd('for')
image.png
这个时候for就要慢于forEach了。所以如果arr是一个Object对象数组,如果用for循环取值的话,一定要把arr[i]提出来,给予一个变量。数据少看不出太多影响,如果数据量大会很不同。
除此之外
forEach要简便一些,如果不知道数组长度,首选就是用forEach。另外for是命令式编程 (适合过程复杂,不能满足条件)注重过程的管控。而forEach是函数式编程 (大部分需求,这个更好)注重最后的结果。
网友评论