var result = [],
a = 3
var total = 0
function foo(a) {
let i = 0
for (; i < 3; i++) {
result[i] = function () {
total += i * a
console.log(total)
}
}
}
foo(1)
result[0]() // 3
result[1]() // 6
result[2]() // 9
今天看到这样一道题,声明变量写在for循环括号外和写在里面居然有这么大的区别,大佬们能不能从执行上下文/作用域/作用域链/V8运行原理的基础上讲解一下
var result = [],
a = 3
var total = 0
function foo(a) {
for (let i = 0; i < 3; i++) {
result[i] = function () {
total += i * a
console.log(total)
}
}
}
foo(1)
result[0]() // 0
result[1]() // 1
result[2]() // 3
let 命名的变量仅在作用域内生效,第一个方法,let i作用域是foo方法内,第二个方法let i 的作用域是每一个for循环.
result数组里面的匿名闭包方法保存了局部变量i的引用
第一个方法 引用的i在for循环结束时已经变成3,所以result数组保存的每个result方法调用时都是使用了这个3
第二个方法,因为作用域是每个for循环,每一次for循环调用实际上都相当于一个新的let i定义,闭包方法保存了每次for循环时i的引用,这时相当于三个方法每个都保存了一个单独的i
所以你看到了这个结果
我说的可能不太清楚
你要了解的知识:let作用域,闭包 搞清楚这两个,你就清楚了