常用的循环类型有for循环、while循环、do-while循环、for-in循环,一个典型的数组处理循环可以采用前三种循环中的任何一种。

<!-- 优化前 -->
<script type="text/javascript">
  for (var i = 0; i < items.length; i++) {
    process(items[i]);
  }

  var j = 0;
  while (j < items.length) {
    process(items[j++]);
  }

  var k = 0;
  do {
    process(items[k++]);
  } while (k < items.length);
</script>

上面的每个循环中,每次运行循环体时都会产生如下操作:

1、一次控制条件中的属性查找(items.length)。

2、一次控制条件中的数值大小比较(i<items.length)。

3、一次控制条件结果是否为true的比较(i<items.length==true)。

4、一次自增操作(i++)。

5、一次数组查找(items[i])。

6、一次函数调用(process(items[i]))。

优化循环的第一步是要减少对象成员及数组项的查找次数,这个例子中每次循环都要查找items.length。这样做很耗时,由于该值在循环运行过程中从未改变,因此产生了不必要的性能损失。提高这个循环性能很简单,只查找一次属性,并把值存储到一个局部变量,然后在控制条件中使用这个变量:

<!-- 优化后 -->
<script type="text/javascript">
  for (var i = 0; len =items.length; i < len ; i++) {
    process(items[i]);
  }

  var j = 0,
      count = items.length;
  while (j < count) {
    process(items[j++]);
  }

  var k = 0,
      num = items.length;
  do {
    process(items[k++]);
  } while (k < num);
</script>

另外还可以通过点到数组的是循序来提高循环性能,倒序循环是一种常用的性能优化方法,但相对来说也比较难理解。

<!-- 颠倒数组优化后 -->
<script type="text/javascript">
  for (var i = items.length; i--) {
    process(items[i]);
  }

  var j = items.length;
  while (j--) {
    process(items[j]);
  }

  var k = items.length - 1;
  do {
    process(items[k]);
  }while (k--);
</script>

本例中使用了倒叙循环,并把减法操作整合在控制条件中。现在每个控制条件只是简单地与零比较。控制条件与true值比较,任何非零数会自动转换为true,而零值等同于false。实际上,控制条件从两次比较(迭代次数少于总数吗?它是否为true?)减少到一次比较(它是true吗?)。每次迭代从两次比较减少到一次,进一步提高了循环速度。通过倒序循环和减少属性查找,你可以看到运行速度比原始版本快了50%~60%。

对比原始版本,每次迭代中只有如下操作:

1、一次控制条件中的比较(i == true);

2、一次减法操作(i--);

3、一次数组查找(items[i]);

4、一次函数调用(process(items[i])).

新的循环代码每次迭代中减少了两次操作,伴随着迭代次数的增加,性能的提升会更趋明显。

延伸阅读


▶ Walkthrough007

更多推荐