视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript循环语句的性能问题
2020-11-27 20:24:39 责编:小采
文档

在我们JavaScript中, 有四种循环类型

  1. for循环

  2. while循环

  3. do-while循环

  4. for-in循环

其中前三种循环在其他语言也很常见
for-in循环对于在学校学过C/C++的同学来说也许很新鲜
它每次迭代的同时会搜索实例和原型属性, 所以它每次迭代便会产生更多的开销
for-in循环最终只有其他三种类型速度的1/7
所以, 除非我们明确需要迭代一个属性数量未知的对象, 否则我们应尽量避免使用for-in
更不要用for-in循环去遍历数组

我们可以这样去迭代一个明确的对象

var props = ['prop1', 'prop2'], i = 0;while(i < props.length){
 fn(obj[props[i++]]);
}

这段代码根据对象中的属性, 创建一个对象属性的数组, 然后通过while循环来遍历属性列表并处理对应属性值
这样就可以不用查找对象的每一个属性, 减少了循环的开销

上面做法的前提是对象内部的属性是已知的
如果我们不知道对象内部的实现
还要处理对象自身的属性,只能这样做了

for(var prop in obj){ if(obj.hasOwnProperty(prop)){
 //...
 }
}

代价是每次迭代都要判断这个属性是不是对象自己的属性而不是继承来的

除了for-in以外, 其他的循环性能都差不多, 所以使用的时候应该去考虑需求从而选择循环类型


相信刚学习编程的小伙伴都是介样写循环的

for(var i = 0; i < arr.length; i++){
 fn(arr[i]);
}

这个循环语句每进行一次迭代, 都要去查找arr中的length属性,这样很耗时
所以我们可以进行优化,

for(var i = 0, len = arr.length; i < len; i++){
 fn(arr[i]);
}

把数组长度值缓存到一个局部变量, 这样问题就解决了
while, do-while也是同理
根据数组长度, 很多浏览器中能节省大概25%的运行时间


我们还可以通过颠倒数组顺序来略微提高性能

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--);

这样做每次迭代控制条件从两次判断(迭代数是否小于总数, 是否为true)
减少为一次判断(是否为true), 进一步提高了循环速度


最后补充几句
我们大家可能都用过一些数组方法比如arr.forEach()或者一些框架的迭代方法比如jQuery的$().each()去遍历数组,
这些方法对数组的每一个元素执行一个函数
尽管它们很方便, 但它们要比普通的循环要慢很多(调用了外部的方法)
在所有情况下, 基于循环的迭代比基于函数的迭代快大约8倍
所以我们在能使用普通循环(for,while,do-while)解决问题的时候尽量用这些普通循环

下载本文
显示全文
专题