之前写面试总结时候写到了var let const区别,【区别位于第9题:阿里淘宝技术部面试一】然后搞了两道广为人知的面试题上去,查资料过程中发现了更多的题,花了一个晚上理解…原谅我还是个小菜鸟:),总结一下。
for(var i=0; i<10; i++){
setTimeout(()=>{
console.log(i)
},1000)
}
// 结果:1秒后输出10个10
1.var定义的i的作用域是整个for函数,每执行一次就有setTimeout函数产生,执行10次所以有10个setTimeout(),1秒后第一个setTimeout()执行,它要输出i,就沿着作用域链去寻找i,找到的时候for早已循环完,i已经变成了10,所以就输出了第一个10,紧接着另外9个setTimeout()也相继执行,所以输出了10给10。
为什么是10个10而不是10个9?
for循环执行顺序:
①var i = 0 ②i<10? ③循环体④i++,i=1
⑤i<10? ⑥循环体⑦i++,i=2…i++,i=9 --》
i<10? --》循环体 --》 i++,i=10 --》i<10?不符合条件,退出循环,此时i=10
for(let i=0; i<10; i++){
setTimeout(()=>{
console.log(i)
},1000)
}
// 结果:1秒后输出0,1,2,3,4,5,6,7,8,9
2.let或const定义的i的作用域是当前循环的块级作用域,所以每次循环都会产生一个新的变量,1秒后10个setTimeout()函数执行找到的i就是之前每个当循环的i,所以是0-9
for(var i=0; i<10; i++){
let temp = i
setTimeout(()=>{
console.log(temp)
},1000)
}
// 结果:1秒后输出0,1,2,3,4,5,6,7,8,9
3.虽然for条件里是var定义的,但是每次执行循环体的时候,当前的i都赋值给了temp,且temp的作用域是当前循环的块级作用域,所以输出0-9
for(let i=0; i<10; i++){
var temp = i
setTimeout(()=>{
console.log(temp)
},1000)
}
// 结果:1秒后输出10个9
4.for循环条件的i是let定义的,所以每次循环都会产生一个新的变量,但是
思考一下如何只用var输出0-9?
。。。
。。。
叮咚~
for(var i=0; i<10; i++){
((i) => {
setTimeout(()=>{
console.log(i)
},1000)
})(i)
// 结果:1秒后输出0,1,2,3,4,5,6,7,8,9
5.每次循环都产生一个立即执行函数,且传入的参数分别是0-9,1秒后10个setTimeout()函数要输出i,所以它们要各自去寻找i,一层层往外找,刚好就在它的父函数里找到了,称为调用其外部函数变量i,分别是0-9
for(var i=0; i<10; i++){
setTimeout((i)=>{
console.log(i)
},1000, i)
}
// 结果:1秒后输出0,1,2,3,4,5,6,7,8,9
6.这是第二种方法。setTimeout(callback[,time[,pram]])
,它的第三个参数就是回调函数传入的参数,也作为当前循环的变量被保存进去了
var a = []
for(var i=0; i<10; i++){
a[i] = function() {
console.log(i)
}
}
a[6]()
// 结果:10
7.10次循环分别给a[0]到a[9]绑定了一个函数,当a6时,函数需要输出i,所以它要沿着作用域链去寻找i,找到的时候用var定义的变量i已经被循环到10了,所以输出10