gpt4 book ai didi

javascript - 为什么在嵌套函数外声明一个计数器变量会使循环变慢 5 倍?

转载 作者:可可西里 更新时间:2023-11-01 02:24:00 25 4
gpt4 key购买 nike

我正在寻找一些我正在重新访问的 JavaScript 遗留代码的微优化,并注意到在最常调用的 for 循环中,计数器在全局范围内声明一次,在使用它们的函数之外。我很好奇这是否确实是一种优化,因此我在 JavaScript 中创建了以下测试用例:

var tmp = 0;

function test(){

let j = 0;

function letItBe(){

for(j = 0; j < 1000; j++){
tmp = Math.pow(j, 2);
}
}

function letItNotBe(){
for(let l = 0; l < 1000; l++){
tmp = Math.pow(l, 2);
}
}

console.time("let it be");
for(var i =0; i < 10000; i++){

letItBe();
}
console.timeEnd("let it be");


console.time("let it not be");
for(var i =0; i < 10000; i++){

letItNotBe();
}
console.timeEnd("let it not be");
}

test();

letItNotBe() 在 Chrome、Firefox 和 NodeJS 中的运行速度明显快于 letItBe()

Chrome : enter image description here

NodeJS:

enter image description here

var 改变 let 没有区别。

最初我的逻辑是,每次调用函数时都声明一个新的计数器变量确实比最初声明一个变量然后简单地重置为 0 慢。然而,事实证明这是完全相反的,区别在于在执行时间是相当可观的。

我的简单解释是,当在使用它的函数之外声明计数器变量时,JS 转换器需要以某种方式引用该变量。因为它在父范围内,所以在递增时需要更多的执行来引用它。然而,这只是盲目猜测。

任何人都可以给出任何有意义的解释为什么会发生这种情况,因为除了我已经拥有的测试之外,我还需要重构代码并给出有意义的解释 mysefl :) 谢谢。

最佳答案

我读过一本书High Performance JavaScript ,作者在第 2 章“数据访问”-“管理范围”部分-“标识符解析性能”部分对此进行了解释。

Identifier resolution isn’t free, as in fact no computer operation really is without some sort of performance overhead. The deeper into the execution context’s scope chain an identifier exists, the slower it is to access for both reads and writes. Consequently, local variables are always the fastest to access inside of a function, whereas global variables will generally be the slowest (optimizing JavaScript engines are capable of tuning this in certain situations).

...

The general trend across all browsers is that the deeper into the scope chain an identifier exists, the slower it will be read from or written to.

...

Given this information, it’s advisable to use local variables whenever possible to improve performance in browsers without optimizing JavaScript engines. A good rule of thumb is to always store out-of-scope values in local variables if they are used more than once within a function.

在您的情况下,letItBeletItNotBe 以相同的方式工作,使用相同的范围外 tmp 变量,并且两者它们都是闭包。唯一的区别是 for 循环的计数器变量:

  • 变量 j 是为函数 test() 定义的,它对于函数 letItBe() 是“超出范围”的,所以执行letItBe() 会让引擎在标识符解析上做更多的工作
  • 变量 l 定义在 for 循环的范围内(参见 let keyword in the for loop ),因此解析速度更快

关于javascript - 为什么在嵌套函数外声明一个计数器变量会使循环变慢 5 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49273398/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com