我听过很多次了.向后计数时JavaScript循环真的更快吗?如果是这样,为什么?我已经看到一些测试套件示例显示反向循环更快,但我找不到任何解释为什么!
我假设它是因为循环不再需要在每次检查它是否完成时评估属性并且它只是检查最终的数值.
即
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
Run Code Online (Sandbox Code Playgroud) 我从书中学到了你应该写这样的循环:
for(var i=0, len=arr.length; i < len; i++){
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
所以arr.length每次都不会计算.
其他人说编译器会对此做一些优化,所以你可以写:
for(var i=0; i < arr.length; i++){
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
我只是想知道哪种是最好的练习方式?
在他的书" 更快的网站"中, Steve Sounders写道,提高循环性能的一种简单方法是将迭代器递减到0而不是递增到总长度(实际上这一章是由Nicholas C. Zakas编写的).根据每次迭代的复杂性,此更改可以比原始执行时间节省高达50%的成本.例如:
var values = [1,2,3,4,5];
var length = values.length;
for (var i=length; i--;) {
process(values[i]);
}
Run Code Online (Sandbox Code Playgroud)
这对于for循环,do-while循环和while循环几乎相同.
我想知道,这是什么原因?为什么要这么快地递减迭代器呢?(我对此技术背景感兴趣,而不是在证明此声明的基准测试中感兴趣.)
编辑:乍一看这里使用的循环语法看起来不对.没有length-1或者i>=0,让我们澄清(我很困惑太).
这是循环语法的一般:
for ([initial-expression]; [condition]; [final-expression])
statement
Run Code Online (Sandbox Code Playgroud)
初始表达 -var i=length
首先评估此变量声明.
条件 -i--
在每次循环迭代之前计算此表达式.它将在第一次通过循环之前递减变量.如果此表达式求值为false循环结束.在JavaScript中是0 == false这样的,如果i最终等于0它被解释为false并且循环结束.
最终表达
在每次循环迭代结束时(在下一次条件评估之前)评估该表达式.这里不需要它是空的.所有三个表达式在for循环中都是可选的.
for循环语法不是问题的一部分,但因为它有点不常见,我认为澄清它是有趣的.也许有一个原因是它更快,因为它使用较少的表达式(0 == false"技巧").
鉴于此代码:
var arr = [];
for (var i = 0; i < 10000; ++i)
arr.push(1);
Run Code Online (Sandbox Code Playgroud)
前锋
for (var i = 0; i < arr.length; ++i) {}
Run Code Online (Sandbox Code Playgroud)
向后
for (var i = arr.length - 1; i >= 0; --i) {}
Run Code Online (Sandbox Code Playgroud)
硬编码转发
for (var i = 0; i < 10000; ++i) {}
Run Code Online (Sandbox Code Playgroud)
为什么向后退得这么快?
我写了一个非常简单的基准:
console.time('var');
for (var i = 0; i < 100000000; i++) {}
console.timeEnd('var')
console.time('let');
for (let i = 0; i < 100000000; i++) {}
console.timeEnd('let')
Run Code Online (Sandbox Code Playgroud)
如果你正在运行Chrome,可以在这里试试(因为NodeJS和Chrome使用相同的JavaScript引擎,虽然版本通常略有不同):
// Since Node runs code in a function wrapper with a different
// `this` than global code, do that:
(function() {
console.time('var');
for (var i = 0; i < 100000000; i++) {}
console.timeEnd('var')
console.time('let');
for (let i = 0; i < 100000000; i++) {}
console.timeEnd('let')
}).call({});Run Code Online (Sandbox Code Playgroud)
结果令我惊讶:
var: 89.162ms
let: 320.473ms
Run Code Online (Sandbox Code Playgroud)
我在Node 4.0.0 && …
考虑到Chrome主要版本尚未发布,Chrome Canary 59 的新型Ignition + Turbofan引擎已经解决了这个问题.测试显示相同的时间let和var声明的循环变量.
原始(现在是静音)问题.
当使用let在forChrome上循环运行速度非常缓慢,相比于移动变量外刚内循环的范围.
for(let i = 0; i < 1e6; i ++);
Run Code Online (Sandbox Code Playgroud)
需要两倍的时间
{ let i; for(i = 0; i < 1e6; i ++);}
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?
Snippet演示了差异,只影响Chrome,只要我记得Chrome支持,就一直如此let.
var times = [0,0]; // hold total times
var count = 0; // number of tests
function test(){
var start = performance.now();
for(let i = 0; i < 1e6; i += 1){};
times[0] += performance.now()-start;
setTimeout(test1,10) …Run Code Online (Sandbox Code Playgroud)忽略所有代码清洁度和可读性,哪个脚本会更快完成?
这个:
for(var i = 0; i < 10; i++){
--do that thing--
}
Run Code Online (Sandbox Code Playgroud)
或这个:
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
Run Code Online (Sandbox Code Playgroud)
或者它们是相同的,性能方面的?
javascript ×7
performance ×5
loops ×4
ecmascript-6 ×2
optimization ×2
for-loop ×1
let ×1
node.js ×1
readability ×1
v8 ×1
while-loop ×1