Javascript 为什么在全局范围内定义变量时for循环需要很长时间?

Javascript 为什么在全局范围内定义变量时for循环需要很长时间?,javascript,for-loop,ecmascript-6,Javascript,For Loop,Ecmascript 6,在下面的示例中,为什么var比let In for循环花费的时间长?我对此做了一些研究,发现var全局定义变量是因为函数作用域,让我们在块作用域中定义变量。这就是为什么“var”比“let”花了很长时间,但仍然无法找到对其原因的实际理解 console.time('letCounter'); for (let letCounter = 0; letCounter < 10500; letCounter++) { console.log('letCounter', letCounte

在下面的示例中,为什么var比let In for循环花费的时间长?我对此做了一些研究,发现var全局定义变量是因为函数作用域,让我们在块作用域中定义变量。这就是为什么“var”比“let”花了很长时间,但仍然无法找到对其原因的实际理解

console.time('letCounter');
for (let letCounter = 0; letCounter < 10500; letCounter++) {
    console.log('letCounter', letCounter);
}
console.timeEnd('letCounter');
// 598.838134765625ms

console.time('varCounter');
for (var varCounter = 0; varCounter < 10500; varCounter++) {
    console.log('varCounter', varCounter);
}
console.timeEnd('varCounter');
// 656.56494140625ms
console.time('letCounter');
对于(让letCounter=0;letCounter<10500;letCounter++){
console.log('letCounter',letCounter);
}
console.timeEnd('letCounter');
//598.838134765625ms
控制台时间('varCounter');
对于(var-varCounter=0;varCounter<10500;varCounter++){
console.log('varCounter',varCounter);
}
控制台.timeEnd('varCounter');
//656.56494140625ms

全局变量的问题是,编译器无法知道内容是否将被“外部”函数访问(即,在编译时主体未知)

例如,
console.log
如果是全局变量,理论上可能会更改
varCounter
。然后必须将变量存储在一个完整的Javascript插槽中(能够包含字符串、数组和对象),然后从该插槽中读回以进行增量

如果变量是本地变量,则如果未捕获变量,则不可能进行访问,因此可以优化变量本身,循环可以检测模式并增加32位整数作为索引,而无需分配完整的Javascript插槽

如果变量是一个函数local
var
,那么情况就不同了,因为外部函数也无法访问它。在这种情况下,如果编译器不够聪明,使用
var
执行可能比使用
let
更快:原因是如果在主体中变量可能被闭包捕获,则必须在每次迭代时分配新的闭包单元格。这不会发生在
var
中,因为作用域是整个函数(而不是
for
循环的主体):

x=[];
对于(设i=0;ii);
}
console.log(x[4]());//显示4

在上面的循环中将
let
更改为
var
,您将得到10,因为所有闭包都捕获相同的
var
单元格。

这些问题的答案正好相反:谢谢您的解释。例如,如果变量是全局变量,console.log(理论上)可以更改varCounter。然后必须将该变量存储在一个完整的Javascript插槽中(能够包含字符串、数组、对象),然后从该插槽中读回以进行增量但是你能解释一下这一部分吗?@Shubham:Javascript是动态类型的,变量可以包含任何对象类型。这意味着变量实际上是指向堆分配对象的指针(或者在某些情况下必须能够包含指针)。对于变量上的每个操作,必须进行类型检查,以确定需要哪些操作,这比仅递增一个数字要慢。如果编译器发现变量只在循环中使用(没有外部访问),那么生成的机器代码理论上可以使用CPU寄存器作为索引。这就是“优化变量”的含义。
 x = [];
 for (let i=0; i<10; ++) {
     x.push(()=>i);
 }
 console.log(x[4]()); // Shows 4