我听过这个问题很多次。JavaScript 循环倒序计数真的更快吗?如果是这样,为什么呢?我看到一些测试套件示例显示反向循环更快,但我找不到任何解释为什么!
我猜这是因为循环不再需要每次评估一个属性来检查它是否完成,而只需针对最终数字值进行检查。
即:
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
我听过这个问题很多次。JavaScript 循环倒序计数真的更快吗?如果是这样,为什么呢?我看到一些测试套件示例显示反向循环更快,但我找不到任何解释为什么!
我猜这是因为循环不再需要每次评估一个属性来检查它是否完成,而只需针对最终数字值进行检查。
即:
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
曾经有人说,在C++中使用--i会更快,因为它只有一个结果,即递减后的值。i--需要将递减后的值存回i,并将原始值保留为结果(j=i--;)。在大多数编译器中,这将使用两个寄存器,而不是一个,可能会导致另一个变量必须写入内存,而不能保留为寄存器变量。
我同意那些认为现在没有区别的人的观点。
--i
更快,https://jsben.ch/RpG0K。jsbench.me: i--
更快,https://jsbench.me/i2kkzuk4kl/1。measurethat.net: --i
更快,https://www.measurethat.net/Benchmarks/ShowResult/162675。 - johny why++
操作比 --
更快,因为 --
操作将执行2的补码,但它发生在硬件内部,这将使其更快,并且 ++
和 --
之间没有什么重大区别,这些操作被认为是CPU中所消耗时间最少的。
for循环
的运行方式如下:
<
, >
, <=
等)中的限制条件。for (var i = Things.length - 1; i >= 0; i--) {
Things[i]
};
将在开始时仅计算一次数组长度,这不需要很长时间,但
for(var i = array.length; i--; )
在每个循环中计算长度,会消耗大量时间。
var i = Things.length - 1; i >= 0; i--
这段代码会多次计算长度。 - Dmitry--
操作会对二进制补码做什么,但我认为它意味着它会否定某些东西。不,它在任何架构上都不会否定任何东西。减去1和加1一样简单,你只需要制作一个借位电路而不是进位电路即可。 - Olathe首先,包括JavaScript在内的所有编程语言中,i++
和i--
所需的时间完全相同。
以下代码所需的时间差异很大。
快速:
for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };
缓慢:
for (var i = 0; i <= Things.length - 1; i++) { Things[i] };
for (var i = Things.length - 1; i >= 0; i--) { Things[i] };
慢速:
for (var i = 0; i <= Things.length - 1; i++) { Things[i] };
附注:由于编译器的优化,Slow 只对某些语言(JavaScript 引擎)而言是慢的。最好的方法是使用 '<' 而非 '<='(或 '=') 以及 '--i' 而非 'i--'。
嗯,我对JavaScript不太清楚,这可能只涉及重新评估数组长度,也可能与关联数组有关(如果只是递减,新条目不太可能需要分配 - 如果数组是稠密的话,某人可能会针对此进行优化)。
在低级汇编语言中,有一种循环指令称为DJNZ(递减并跳转如果非零)。因此,递减和跳转都在一个指令中进行,可能比INC和JL / JB(增加,如果小于/增加,如果下面)要稍微快一些。而且,与零进行比较比与其他数字进行比较更简单。但所有这些都非常微小,还取决于目标架构(例如,在智能手机上的Arm上可能会有所不同)。
我不会期望这些底层差异对解释性语言产生如此重大的影响,我只是没有在回复中看到DJNZ,所以想分享一个有趣的想法。
dec/jnz
代替inc/cmp/jne
,显然ARM也有类似的东西。我相信这不是JavaScript差异的原因;这是由于在循环条件中有更多要评估的内容。 - Peter Cordes简单来说,i-- 和 i++ 所需的时间是相同的。
但在这种情况下,当你进行递增操作时,处理器会每次将变量加1时评估 .length,而在递减操作中,在这种情况下,它只会评估一次 .length 直到我们得到0。
帮助他人避免头疼 --- 投票支持这个问题!!!
这个页面上最受欢迎的答案在Firefox 14上不起作用,也无法通过jsLinter。 "while"循环需要一个比较运算符,而不是一个赋值运算符。它可以在Chrome、Safari甚至IE上工作。但在Firefox中却失败了。
这是有问题的!
var i = arr.length; //or 10
while(i--)
{
//...
}
这个会有用的!(在Firefox上能正常工作,通过了jsLinter)
var i = arr.length; //or 10
while(i>-1)
{
//...
i = i - 1;
}
while (i--)
并且可以跨多个浏览器工作。你的测试可能有什么奇怪的地方吗?你是在使用Firefox 14的beta版本吗? - Matt Browne很棒,有很多标记但没有答案:D
简单来说,与零进行比较始终是最快的比较方式。
因此,(a == 0)实际上比(a == 5)更快地返回True。
这很微不足道,但在集合中有1亿行时,它是可以测量的。
例如,在循环中你可能会说 i <= array.length 并增加 i
在向下循环中,你可能会说 i >= 0 并减少i。
比较速度更快。而不是循环的“方向”。
for
循环更快,因为上界(嘿嘿,下界)循环控制变量不需要被定义或从对象中获取;它是一个常数零。 - Josh Stodola