我从书中学到,你应该这样写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
}
我只是想知道在实践中哪种方法是最好的?
当前回答
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/
其他回答
http://jsperf.com/caching-array-length/60
我准备的最新版本的test(通过重用旧版本)显示了一件事。
缓存长度并不是那么重要,但也没有坏处。
在Chrome、Opera和Firefox中,在我的Debian Squeeze 64位(我的桌面硬件)中,每次第一次运行上面链接的测试(在新打开的选项卡上),最后4个片段(图表中的第3、第5、第7和第10)的结果都是最好的。随后的运行给出了完全不同的结果。
性能方面的结论很简单:
使用for循环(向前)并使用!==而不是<进行测试。 如果以后不需要重用数组,那么while循环减去长度和破坏性shift()-ing数组也是有效的。
博士tl;
现在(2011.10)下面的模式看起来是最快的。
for (var i = 0, len = arr.length; i !== len; i++) {
...
}
注意缓存。长度在这里并不重要,所以您可以只测试I !== arr。长度和性能不会下降,但是代码会变短。
PS:我知道在snippet with shift()中,它的结果可以用来代替访问第0个元素,但我在重用以前的修订(有错误的while循环)后忽视了这一点,后来我不想失去已经获得的结果。
虽然这是一个非常古老的问题,但也是一个非常有趣的问题,
请原谅我稍微改变一下这个问题,但我会在最后回答这个问题。
这个问题让我问自己,在js中是否有更好的循环方法:
所以我做了一些测试,以下是我的发现:
对于1000_000记录:最好是forEach。
对于100条记录:这根本不重要。
回到你刚才的问题:
我创建的例子和问题不完全一样。但我发现了一些有趣的事情:
首先,就像你说的,arr。如果它在比较语句I < arr内,Length每次都会计算。长度……
注意:下面的arrLength变量不超过1000_000条记录的数量。
例如:这不会工作
但是这个会
这需要0.036秒。与数字不变的情况相比,这是非常大的……
总之,
最好使用FOREACH
在你的例子中,i<arr。长度需要更多的时间(通常在1.3左右)
请参阅测试: 查看测试
现在是2022年底
有时根本没有用数组长度计算:
如果你有一个索引为var myArray =[1,2,3,4,25,99999999999999]的数组,使用任何索引为1的槽数组(包括forEach)的解决方案都是非常缓慢的。
对我来说,最好的解决方案是:
for(let _i in myArray ) {
if(myArray[_i]) {
(function(s) {
///
})(myArray[_i])
}
}
另一个jsperf.com测试:http://jsperf.com/while-reverse-vs-for-cached-length
反向while循环似乎是最快的。唯一的问题是while(——i)将停止于0。我怎么能访问数组[0]在我的循环那么?
**缓存数组的长度在循环内,一些秒的时间将被规避。取决于数组中的项,如果数组中有更多项,则时间毫秒有很大差异*
**
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***
**