JavaScript 循环性能 - 为什么将迭代器递减到 0 比递增更快

标签 javascript performance loops

在他的书中Even Faster Web Sites 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]);
}

这与 for 循环、do-while 循环和 while 循环几乎相同。

请问这是什么原因呢? 为什么递减迭代器要快得多?(我感兴趣的是这方面的技术背景,而不是证明这一说法的基准测试。)


编辑:乍一看,这里使用的循环语法看起来是错误的。没有 length-1i>=0,所以让我们澄清一下(我也很困惑)。

这是一般的 for 循环语法:

for ([initial-expression]; [condition]; [final-expression])
   statement
  • 初始表达式 - var i=length

    首先评估此变量声明。

  • 条件 - i--

    此表达式在每次循环迭代之前求值。它会在第一次通过循环之前递减变量。如果此表达式的计算结果为 false,则循环结束。在 JavaScript 中是 0 == false 所以如果 i 最终等于 0 它被解释为 false 并且循环结束.

  • 最终表达式

    此表达式在每次循环迭代结束时求值(在下一次求值条件之前)。这里不需要它,它是空的。所有三个表达式在 for 循环中都是可选的。

for 循环语法不是问题的一部分,但因为它有点不常见,所以我认为澄清它很有趣。也许它更快的一个原因是因为它使用了更少的表达式(0 == false“技巧”)。

最佳答案

我不确定 Javascript,在现代编译器下它可能无关紧要,但在“过去”这段代码中:

for (i = 0; i < n; i++){
  .. body..
}

会产生

move register, 0
L1:
compare register, n
jump-if-greater-or-equal L2
-- body ..
increment register
jump L1
L2:

而后向计数代码

for (i = n; --i>=0;){
  .. body ..
}

会产生

move register, n
L1:
decrement-and-jump-if-negative register, L2
.. body ..
jump L1
L2:

所以在循环内部它只执行了两个额外的指令而不是四个。

关于JavaScript 循环性能 - 为什么将迭代器递减到 0 比递增更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30159842/

相关文章:

javascript - 多次滑动函数调用

javascript - 仅在特定页面中滚动显示 div

javascript - 使用 Async/Await 捕获错误

performance - 优化 Redis-Graph 查询性能(匹配)

php - 电子商务网站服务器性能缓慢

loops - 我如何在最大值中使用循环来绘制多个向量?

java继承删除子对象

javascript - 将数组发送到 PHP Web 服务并从 MySQL 数据库返回数组

java - 一个 jar 中的多个 java 进程

python - 在C中查看日志文件