ES5中for循环的变量如果用var来定义的话,因为var不受块级作用域的影响,所以他会提升到全局变量中去,但是ES6中用let可以解决这个问题,但是不知道他的内在逻辑是怎样的,后来我再我看了一些资料后,我总结出了我自认为还满意的结果.
{
let i = 0;
// 判断i的大小
{
let i = "a";
console.log(i);
}
i = i + 1;
// 判断i的大小
{
let i = "a";
console.log(i);
}
i = i + 1;
// 判断i的大小
{
let i = "a";
console.log(i);
}
}
因为let定义的变量是受当前作用域管控的,就意味着如果他在子级作用域中声明了一个和父级作用域一样的变量,那么他就是子级作用域里面一个全新的变量,而for循环中()里面其实相当于一个父级作用域,{}内部相当于子级作用域,然后for循环的实现就跟我上述的代码一样,首先再父级作用域中用let声明了一个变量,然后再进行判断,然后再执行子级作用域里面的代码,但是这样的话就不能解释那个闭包的问题了
let arr = [];
for (let i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i);
};
}
for (var j = 0; j < 10; j++) {
arr[j]();
}
就上面的代码如果有闭包的存在的话,他还是会打印0~9,但如果用var来定义i的话,就会打印10个10,这时候如果你用最上面的代码逻辑来解释的话就不成立了,因为他按道理会拿到最后的i值也就是10,所以他会打印10个10,但是结果他打印的0~9,所以我认为他可能在他的子级作用域里面声明了let i = 0,就把当时的父级作用域里面的i的值在子级作用域里面重新声明了一遍,这样的话他执行这个函数的时候就会拿到子级作用域里面的值了,这样的话打印0~9也就合理了,但是这样的话又会和最上面的代码冲突,因为如果他用重新定义变量的方式保存了当时父级作用域里面的i的话,因为let定义的变量是不可以被重复定义的,就会报错,但是从结果来说并没有报错,那么我们是不是就可以认为在子级作用域中是没有用let重新定义一个i的,那么你这时候可能就会有点懵了,因为他有时候保存,有时候又不保存是为什么呢?我认为他可能是会检测是否有变量被携带出去了,如果被携带出去就会保存变量,当然这时候又会有另外的问题
let arr = [];
for (let i = 0; i < 10; i++) {
let i = 1;
arr[i] = function () {
console.log(i);
};
}
arr[1]();
就如果你跟上面一样写的话他就会打印1出来,而且他也没有在子级作用域中保存变量,因为let在同一作用域下是不可以重复声明的,但是他还是执行出来了,所以就看似和上面的结论有点矛盾,不过你只要把上面的结论再加一个如果子级作用域中有和父级作用域相同的let声明的变量的话,他就不会保存,这样的话就可以解释得通了。
仅供思考提供一个思路如果有更好的方案请大家再评论区提出,谢谢大家看到这里