JS编程建议——21:推荐提高循环性能的策略(2)

建议21:推荐提高循环性能的策略(2)
在每个循环中,每次运行循环体都要发生如下操作:
第1步,在控制条件中读一次属性(items.length)。
第2步,在控制条件中执行一次比较(i < items.length)。
第3步,比较操作,观察条件控制体的运算结果是不是true(i < items.length == true)。
第4步,一次自加操作(i++)。
第5步,一次数组查找(items[i])。
第6步,一次函数调用(process(items[i]))。
在这些简单的循环中,即使没有太多的代码,每次迭代都要进行这6步操作。代码运行速度很大程度上由process()对每个项目的操作所决定,即便如此,减少每次迭代中操作的总数也可以大幅度提高循环的整体性能。
优化循环的第一步是减少对象成员和数组项查找的次数。在大多数浏览器上,这些操作比访问局部变量或直接量需要更长时间。例如,在上面代码中,每次循环都查找items.length,这是一种浪费,因为该值在循环体执行过程中不会改变,因此产生了不必要的性能损失。我们可以简单地将此值存入一个局部变量中,在控制条件中使用这个局部变量,从而提高了循环性能,例如:

  1. for (var i=0, len=items.length; i < len; i++){
  2. process(items[i]);
  3. }
  4. var j=0, count = items.length;
  5. while (j < count){
  6. process(items[j++]);
  7. }
  8. var k=0, num = items.length;
  9. do {
  10. process(items[k++]);
  11. } while (k < num);
    这些重写后的循环只在循环执行之前对数组长度进行一次属性查询,使控制条件中只有局部变量参与运算,因此速度更快。根据数组的长度,在大多数浏览器上总循环时间可以节省大约25%,在IE浏览器中可节省50%。

还可以通过改变循环的顺序来提高循环性能。通常,数组元素的处理顺序与任务无关,可以从最后一个开始,直到处理完第一个元素。倒序循环是编程语言中常用的性能优化方法,不过一般不太容易理解。在JavaScript 中,倒序循环可以略微提高循环性能,例如:

  1. for (var i=items.length; i--; ){
  2. process(items[i]);
  3. }
  4. var j = items.length;
  5. while (j--){
  6. process(items[j]);
  7. }
  8. var k = items.length-1;
  9. do {
  10. process(items[k]);
  11. } while (k--);
    在上面代码中使用了倒序循环,并且在控制条件中使用了减法。每个控制条件只是简单地与零进行比较。控制条件与true 值进行比较,任何非零数字自动强制转换为true,而零等同于false。实际上,控制条件已经从两次比较减少到一次比较。将每次迭代中两次比较减少到一次可以大幅度提高循环速度。通过倒序循环和最小化属性查询,可以看到执行速度比原始版本提升了50%~60%。

与原始版本相比,每次迭代中只进行如下操作:
第1步,在控制条件中进行一次比较(i == true)。
第2步,一次减法操作(i--)。
第3步,一次数组查询(items[i])。
第4步,一次函数调用(process(items[i]))。
新循环的每次迭代中减少两个操作,随着迭代次数的增长,性能将显著提升。

时间: 2024-08-30 18:35:27

JS编程建议——21:推荐提高循环性能的策略(2)的相关文章

JS编程建议——23推荐提高条件性能的策略

建议23:推荐提高条件性能的策略与循环相似,条件表达式决定JavaScript 运行流的走向.与其他语言一样,JavaScript也采用了if 和switch 两种条件结构.由于不同浏览器针对流程控制进行了不同的优化,因此两者在性能上并没有特别大的差异,主要还是根据需求形式进行分析和选择:条件数量较大,建议选择switch 结构,而不是if结构,这样可以使代码更易读:如果条件较少时,建议选择if结构. //条件少 if(found) { //执行代码 } else { //执行代码 } //条件

JS编程建议——21:推荐提高循环性能的策略(1)

建议21:推荐提高循环性能的策略(1)每次运行循环体时都会产生性能开销,增加总的运行时间,即使是循环体中最快的代码,累计迭代上千次,也将带来不小的负担.因此,减少循环的迭代次数可获得显著的性能提升.例如: var iterations = Math.floor(items.length / 8), startAt = items.length % 8, i = 0; do { switch(startAt) { case 0: process(items[i++]); case 7: proce

JS编程建议——46:提高正则表达式执行效率

建议46:提高正则表达式执行效率(1)关注如何让匹配更快失败正则表达式处理慢往往是因为匹配失败过程慢,而不是匹配成功过程慢.使用正则表达式匹配一个很大字符串的一小部分,情况更为严重,正则表达式匹配失败的位置比匹配成功的位置要多得多.一个修改使正则表达式匹配更快但失败更慢,例如,通过增加所需的回溯次数尝试所有分支的排列组合,这通常是一个失败的修改.(2)正则表达式以简单的.必需的字元开始最理想的情况是,一个正则表达式的起始字元应当尽可能快速地测试并排除明显不匹配的位置.用于此目的好的起始字元通常是

JS编程建议——29:准确使用循环体(1)

建议29:准确使用循环体(1)1.选择正确的循环体在大多数编程语言中,代码执行时间多数消耗在循环的执行上.在一系列编程模式中,循环是最常用的模式之一,因此也是提高性能必须关注的地方之一.理解JavaScript 中循环对性能的影响至关重要,因为死循环或长时间运行的循环会严重影响用户体验.JavaScript定义了4种类型的循环:第一种循环是标准的for循环,与C语言使用同样的语法: for (var i=0; i < 10; i++){ //循环体 } for循环是最常用的循环结构,它由4部分组

JS编程建议——37:推荐使用replace(1)

建议37:推荐使用replace(1)String对象的replace方法包含两个参数,第一个参数表示执行匹配的正则表达式,也可以传递字符串,第二个参数表示准备代替匹配的子字符串,例如,把字符串html替换为htm. var b = s.replace("html", "htm" ); 与search和match方法不同,replace方法不会把字符串转换为正则表达式对象,而是以字符串直接量的文本模式进行匹配.第二个参数可以是替换的文本,或者是生成替换文本的函数,把

JS编程建议——59:推荐动态调用函数

建议59:推荐动态调用函数调用函数更便捷的方式是使用Function对象的call和apply方法.apply与call方法在本质上没有太大区别,只不过它们传递给函数的参数方式不同, apply是以数组形式进行参数传递,而call方法可以同时传递多个值.如果某个函数仅能够接收多个参数列表,而现在希望把一个数组的所有元素作为参数进行传递,那么使用apply方法就显得非常便利.function max(){ var m = Number.NEGATIVE_INFINITY; // 声明一个负无穷大的

JS编程建议——28:使用查表法提高条件检测的性能

建议28:使用查表法提高条件检测的性能当有大量离散值需要测试时,使用if和switch都比使用查表法要慢得多.在JavaScript中查表法可通过数组或普通对象实现,查表法访问数据比if和switch更快,特别是当条件体的数目很大时.与if和switch相比,查表法不仅非常快,而且当需要测试的离散值数量非常大时,也有助于保持代码的可读性.例如,在下面代码中,使用switch检测value值. switch(value) { case 0: return result0; case 1: retu

JS编程建议——37:推荐使用replace(2)

建议37:推荐使用replace(2)在上面的示例代码中,函数f()的参数为特殊字符"$1",它表示正则表达式/(bw+b)/中小括号每次匹配的文本.然后在函数体内对这个匹配文本进行处理,截取其首字母并转换为大写形式,之后返回新处理的字符串.replace方法能够在原文本中使用这个返回的新字符串替换每次匹配的子字符串.对于上面的示例,可以使用小括号来获取更多匹配文本的信息.例如,直接利用小括号传递单词的首字母,然后进行大小写转换处理: var s = 'script language

JS编程建议——68:推荐使用链式语法

建议68:推荐使用链式语法使用过jQuery框架的读者,都会对jQuery简洁的语法.灵巧的用法赞叹不已,其中一个最大亮点就是jQuery的链式语法.在JavaScript中,很多方法没有返回值,一些设置或修改对象的某个状态却不返回任何值的方法就是典型的例子.如果让这些方法返回this,而不是undefined,那么就要启用级联功能,即所谓的链式语法.在一个级联中,单独一条语句可以连续调用同一个对象的很多方法.getElement('box'). move(350, 150). width(10