我从书中学到,你应该这样写for循环:
for(var i=0, len=arr.length; i < len; i++){
// blah blah
}
所以arr。每次不计算长度。
其他人说编译器会做一些优化,所以你可以这样写:
for(var i=0; i < arr.length; i++){
// blah blah
}
我只是想知道在实践中哪种方法是最好的?
我从书中学到,你应该这样写for循环:
for(var i=0, len=arr.length; i < len; i++){
// blah blah
}
所以arr。每次不计算长度。
其他人说编译器会做一些优化,所以你可以这样写:
for(var i=0; i < arr.length; i++){
// blah blah
}
我只是想知道在实践中哪种方法是最好的?
当前回答
“最好”是指纯粹的表演吗?还是性能和可读性?
纯性能“最佳”是这个,它使用缓存和++前缀操作符(我的数据:http://jsperf.com/caching-array-length/189)
for (var i = 0, len = myArray.length; i < len; ++i) {
// blah blah
}
我认为无缓存的for循环是执行时间和程序员读取时间的最佳平衡。每一个从C/ c++ /Java开始的程序员都不会浪费时间去阅读这本书
for(var i=0; i < arr.length; i++){
// blah blah
}
其他回答
**缓存数组的长度在循环内,一些秒的时间将被规避。取决于数组中的项,如果数组中有更多项,则时间毫秒有很大差异*
**
sArr; //Array[158];
for(var i = 0 ; i <sArr.length ; i++) {
callArray(sArr[i]); //function call
}
***end: 6.875ms***
**
**
sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
callArray(sArr[i]); //function call
}
***end: 1.354ms***
**
2014年While回来了
要有逻辑性。
看看这个
for( var index = 0 , length = array.length ; index < length ; index++ ) {
//do stuff
}
需要创建至少2个变量(index,length) 需要检查索引是否小于长度 需要增加索引 for循环有3个参数
现在告诉我为什么这个要比
var length = array.length;
while( --length ) { //or length--
//do stuff
}
一个变量 没有检查 指数下降(机器更喜欢这样) While只有一个参数
当Chrome 28显示for循环比while快时,我完全困惑了。 这一定是某种
“嗯,每个人都在使用for循环,让我们专注于这个 为铬开发。”
但是现在,在2014年,while循环又回到了chrome上。它快了2倍,在其他/旧浏览器上它总是更快。
最近我做了一些新的测试。现在在现实环境中,这些短代码毫无价值,jsperf实际上不能正确执行while循环,因为它需要重新创建数组。长度也需要时间。
你无法在jsperf上获得while循环的实际速度。
您需要创建自己的自定义函数,并使用window.performance.now()进行检查。
是的……while循环不可能简单地更快。
真正的问题实际上是dom操作/渲染时间 画图时间,随你怎么叫。
例如,我有一个画布场景,我需要计算坐标和碰撞…这是在10-200微秒(不是毫秒)之间完成的。它实际上需要不同的毫秒来渲染所有内容。和DOM中一样。
BUT
在某些情况下,还有另一种使用for循环的超级性能方式……例如复制/克隆一个数组
for(
var i = array.length ;
i > 0 ;
arrayCopy[ --i ] = array[ i ] // doing stuff
);
注意参数的设置:
与while循环中一样,我只使用一个变量 需要检查索引是否大于0; 正如你所看到的,这种方法与每个人都使用的正常for循环不同,因为i在第3个参数内做东西,并且i也直接在数组内减少。
说到这里,这证实了机器喜欢
我想把它写得短一点,去掉一些无用的东西,用同样的风格写了这篇文章:
for(
var i = array.length ;
i-- ;
arrayCopy[ i ] = array[ i ] // doing stuff
);
即使它更短,但再次使用i似乎会减慢一切。 它比之前的for循环和while循环慢了1/5。
注:;在没有{}的for looo后面非常重要
即使我只是告诉你,jsperf不是测试脚本的最佳方式。我在这里加了两个循环
http://jsperf.com/caching-array-length/40
这里有另一个关于javascript性能的答案
https://stackoverflow.com/a/21353032/2450730
这个答案是为了展示编写javascript的性能方法。所以如果你看不懂,问一下,你会得到答案,或者读一本关于javascript的书http://www.ecma-international.org/ecma-262/5.1/
试试这个:
var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
Benchmarking [10000000] element array...
The fastest [for ++] took [76762166ns]
┌─────────┬───────────────────────┬────────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼────────────┼──────────┤
│ 0 │ 'for ++' │ 76762166 │ 1 │
│ 1 │ 'for of' │ 82407583 │ 1.07 │
│ 2 │ '--while forward' │ 83723083 │ 1.09 │
│ 3 │ 'do while forward --' │ 83942958 │ 1.09 │
│ 4 │ '--do while forward' │ 84225584 │ 1.1 │
│ 5 │ 'while forward --' │ 85156957 │ 1.11 │
│ 6 │ '--while >= 0' │ 89745916 │ 1.17 │
│ 7 │ '++ do while' │ 90306542 │ 1.18 │
│ 8 │ 'for !== ++' │ 90319083 │ 1.18 │
│ 9 │ '-- for' │ 90360167 │ 1.18 │
│ 10 │ 'for i length --' │ 90558833 │ 1.18 │
│ 11 │ '++ for' │ 90616125 │ 1.18 │
│ 12 │ 'do while ++' │ 90657541 │ 1.18 │
│ 13 │ '--for i length' │ 90757708 │ 1.18 │
│ 14 │ 'for --' │ 90799875 │ 1.18 │
│ 15 │ '++ while' │ 92697417 │ 1.21 │
│ 16 │ '++ for !==' │ 94488209 │ 1.23 │
│ 17 │ 'pop' │ 108399917 │ 1.41 │
│ 18 │ 'while ++' │ 109276500 │ 1.42 │
│ 19 │ 'forEach call' │ 147140124 │ 1.92 │
│ 20 │ 'forEach' │ 148886207 │ 1.94 │
│ 21 │ 'map' │ 207100583 │ 2.7 │
│ 22 │ 'Array from' │ 353166207 │ 4.6 │
│ 23 │ 'flatMap' │ 1213152082 │ 15.8 │
│ 24 │ 'Object.keys map' │ 1294475333 │ 16.86 │
│ 25 │ 'for in' │ 1338988749 │ 17.44 │
└─────────┴───────────────────────┴────────────┴──────────┘
在Macbook Air M1 2020上测试。NodeJS 18。
对于包含10_000_000个元素的数组,循环标准胜出。关于其他情况,请参阅我的要点:https://gist.github.com/episage/076ded007d0583f6a275f93a8c9c8047#file-result-txt
大声喊出@DungGramer。我修复了bug并提高了他的基准测试。
现在是2018年,所以更新一下会很好……
我真的不同意这个公认的答案。 它在不同的浏览器上有所不同。有的forEach更快,有的for循环,有的while 这里是所有方法的基准https://jsben.ch/mW36e
arr.forEach( a => {
// ...
}
因为你可以看到很多for循环,比如for(a = 0;…)值得一提的是,如果没有'var',变量将被全局定义,这可能会极大地影响速度,因此它会变慢。
Duff's device run faster on opera but not in firefox var arr = arr = new Array(11111111).fill(255); var benches = [ [ "empty", () => { for(var a = 0, l = arr.length; a < l; a++); }] , ["for-loop", () => { for(var a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () => { for(var a = 0, l = arr.length; a < l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () => { for(var a = 0; a < arr.length; ++a ) var b = arr[a] + 1; }] , ["reverse for-loop", () => { for(var a = arr.length - 1; a >= 0; --a ) var b = arr[a] + 1; }] ,["while-loop", () => { var a = 0, l = arr.length; while( a < l ) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () => { var a = arr.length - 1; // CAREFUL do { var b = arr[a] + 1; } while(a--); }] , ["forEach", () => { arr.forEach( a => { var b = a + 1; }); }] , ["for const..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( const a in ar ) { var b = a + 1; } }] , ["for let..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( let a in ar ) { var b = a + 1; } }] , ["for var..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( var a in ar ) { var b = a + 1; } }] , ["Duff's device", () => { var len = arr.length; var i, n = len % 8 - 1; if (n > 0) { do { var b = arr[len-n] + 1; } while (--n); // n must be greater than 0 here } n = (len * 0.125) ^ 0; if (n > 0) { do { i = --n <<3; var b = arr[i] + 1; var c = arr[i+1] + 1; var d = arr[i+2] + 1; var e = arr[i+3] + 1; var f = arr[i+4] + 1; var g = arr[i+5] + 1; var h = arr[i+6] + 1; var k = arr[i+7] + 1; } while (n); // n must be greater than 0 here also } }]]; function bench(title, f) { var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`); } var globalVarTime = bench( "for-loop without 'var'", () => { // Here if you forget to put 'var' so variables'll be global for(a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }); var times = benches.map( function(a) { arr = new Array(11111111).fill(255); return [a[0], bench(...a)] }).sort( (a,b) => a[1]-b[1] ); var max = times[times.length-1][1]; times = times.map( a => {a[2] = (a[1]/max)*100; return a; } ); var template = (title, time, n) => `<div>` + `<span>${title} </span>` + `<span style="width:${3+n/2}%"> ${Number(time.toFixed(3))}msec</span>` + `</div>`; var strRes = times.map( t => template(...t) ).join("\n") + `<br><br>for-loop without 'var' ${globalVarTime} msec.`; var $container = document.getElementById("container"); $container.innerHTML = strRes; body { color:#fff; background:#333; font-family:helvetica; } body > div > div { clear:both } body > div > div > span { float:left; width:43%; margin:3px 0; text-align:right; } body > div > div > span:nth-child(2) { text-align:left; background:darkorange; animation:showup .37s .111s; -webkit-animation:showup .37s .111s; } @keyframes showup { from { width:0; } } @-webkit-keyframes showup { from { width:0; } } <div id="container"> </div>