javascript中 for(let i =0;...;...) 与let i=0;for(;....;...)循环的区别

趴...
  • 3
新手上路,请多包涵
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
回复
阅读 931
4 个回答

let 命名的变量仅在作用域内生效,第一个方法,let i作用域是foo方法内,第二个方法let i 的作用域是每一个for循环.
result数组里面的匿名闭包方法保存了局部变量i的引用
第一个方法 引用的i在for循环结束时已经变成3,所以result数组保存的每个result方法调用时都是使用了这个3
第二个方法,因为作用域是每个for循环,每一次for循环调用实际上都相当于一个新的let i定义,闭包方法保存了每次for循环时i的引用,这时相当于三个方法每个都保存了一个单独的i
所以你看到了这个结果

我说的可能不太清楚
你要了解的知识:let作用域,闭包 搞清楚这两个,你就清楚了

不同位置下let定义的作用域是不同的,在for内 和 for外 也存在这样的情况,比如:

let a=0;
for(;a<10;a++){
    console.log("a="+a);
}
console.log("out For 1");
console.log("a="+a);
for(let b=0;b<10;b++){
    console.log("b="+b);
}
console.log("out For 2");
console.log("b="+b);

你运行上述代码就可以找到规律啦。

这个是作用域的问题。
var 全局
let const 局部
以let来说,你定义在一个function中,那么他在这function中的任意位置都能被访问到,function外部则无法使用,而如果你是定义在for/swaich/forEach等循环体中,那他的生效范围只在该循环体里面,function里面循环体外面也无法获取该变量

let 写在 for 的循环头或循环里,每次循环对let都形成一个独立的作用域。for循环对var则形不成作用域。

var result = [];
function foo() {
    for (var i=0; i < 3; i++) {
        let m = 1;
        var n = 1;
        result[i] = function () {
            console.log('m='+m,'n='+n);
            m++;
            n++
        }
    }
}
foo()

result[0]() //m=1 n=1
result[1]() //m=1 n=2
result[2]() //m=1 n=3

result[0]() //m=2 n=4
result[1]() //m=2 n=5
result[2]() //m=2 n=6
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏