【发布时间】:2018-03-14 09:00:38
【问题描述】:
我正在寻找一些我正在重新访问的 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();
在 Chrome、Firefox 和 NodeJS 中,letItNotBe() 的运行速度明显快于 letItBe()
NodeJS:
用 var 改变 let 没有任何区别。
最初我的逻辑是,每次调用函数时声明一个新的计数器变量确实比最初声明一个变量然后简单地重置为 0 慢。然而,事实证明这是完全相反的和不同的在执行时间上是相当实质性的。
我的简单解释是,当计数器变量在使用它的函数之外声明时,JS 转译器需要以某种方式引用这个变量。而且由于它在父范围内,因此在递增时需要更多的执行来引用它。但这只是盲目的猜测。
任何人都可以给出任何有意义的解释为什么会发生这种情况,因为除了我已经拥有的测试之外,我需要重构代码并给出有意义的解释 mysefl :) 谢谢。
【问题讨论】:
-
可能是因为它不必在 for 循环之外的范围内查找变量。
-
@GeorgeJempty 是吗?这也是我的猜测......但它是吗?
-
@PeterCordes 颠倒顺序没有任何改变,结果相同。进行更多的迭代也不会改变任何事情。调整 CPU 时钟速度,没有任何改变。连续运行两个函数 2 次,没有任何变化。 :)
-
@Liam 是的,它可以计算物理和粒子之间的碰撞,它是 O(n^2) 并且每个 FPS 都会调用它
-
@Liam 知道原因可能很重要,这样您就可以避免进行缓慢的迭代。此外,我们不应从字面上坚持代码示例,而应始终将这些问题视为通用问题,其中问题中的代码只是该通用问题的单个实现。这样,cmets 和可能的答案对未来的读者也更有用。
标签: javascript optimization micro-optimization