我在浏览我found this:
var i, len;
for(i = 0, len = array.length; i < len; i++) {
//...
}
我的第一个想法是:
普通循环(不缓存长度的循环)每次检查array.length
吗?
答案 0 :(得分:25)
由三部分组成的循环执行如下:
for (A; B; C)
A - Executed before the enumeration
B - condition to test
C - expression after each enumeration (so, not if B evaluated to false)
所以,是的:如果数组构造为.length
,则会在每个枚举中检查数组的for(var i=0; i<array.length; i++)
属性。对于微优化,将数组的长度存储在临时变量中是有效的(另请参阅:What's the fastest way to loop through an array in JavaScript?)。
相当于for (var i=0; i<array.length; i++) { ... }
:
var i = 0;
while (i < array.length) {
...
i++;
}
答案 1 :(得分:9)
Is it worth it? (obviously yes, why else he will do it this way?)
绝对是的。因为,正如你所说,循环每次都会计算数组长度。所以这将导致巨大的开销。在您的firebug或chrome dev工具vs。
中运行以下代码片段// create an array with 50.000 items (function(){ window.items = []; for (var i = 0; i < 50000; i++) { items.push(i); } })(); // a profiler function that will return given function's execution time in milliseconds var getExecutionTime = function(fn) { var start = new Date().getTime(); fn(); var end = new Date().getTime(); console.log(end - start); } var optimized = function() { var newItems = []; for (var i = 0, len = items.length; i < len; i++) { newItems.push(items[i]); } }; var unOptimized = function() { var newItems= []; for (var i = 0; i < items.length; i++) { newItems.push(items[i]); } }; getExecutionTime(optimized); getExecutionTime(unOptimized);
以下是各种浏览器的近似结果
Browser optimized unOptimized Firefox 14 26 Chrome 15 32 IE9 22 40 IE8 82 157 IE7 76 148
所以再考虑一下,并使用优化方式:)
注意:我试图在jsPerf上运行此代码,但我现在无法访问jsPerf。我想,当我尝试的时候它已经失效了。
答案 2 :(得分:0)
这样做的一个原因是,如果您在循环期间向数组添加元素但不想迭代它们。假设您要将[1,2,3]转换为[1,2,3,1,2,3]。你可以用:
var initialLength = items.length;
for(var i=0; i<initialLength; ++i) {
items.push(items[i]);
}
如果你没有在循环之前保存长度,那么array.length将继续增加,循环将一直运行,直到浏览器崩溃/杀死它。
除此之外,正如其他人所说,它对性能有轻微影响。我不会养成这样做的习惯,因为“过早的优化是所有邪恶的根源”。另外,如果在循环期间更改数组的大小,执行此操作可能会破坏您的代码。例如,如果在循环期间从数组中删除元素但是继续将i
与先前的数组大小进行比较,那么循环将尝试访问超出新大小的元素。
答案 3 :(得分:0)
我一直认为JavaScript长度只是数组对象的一个属性,由之前的数组操作预先计算 - 创建,添加,删除 - 或被用户覆盖,所以你只需要查找变量?我必须承认我刚刚假设因为缺少括号,但是看一下array.length的MDN页面,它似乎说同样的事情。
在长度为方法或长度的语言中,通过标准库函数计算,然后在运行循环之前预先计算长度,以便每次迭代都不计算数组,特别是对于大型数据集。即便如此,在像Python这样的现代高级语言中,len()只返回数组对象的length属性。
因此,除非我错了,复杂性只是O(1),从这个角度来看,即使变量比查找每个传递的属性稍快,它也不值得在保护性环路范围之外创建/重用其他变量的潜在麻烦。
然而,我怀疑在这种情况下,示例程序员选择这种方法的原因仅仅是他们用另一种语言学习的习惯并且是前进的JavaScript。
答案 4 :(得分:0)
是的 它每次都检查 array.length,但是如果我们不想为增加的数组运行循环,那么在这种情况下,我们可以使用 forEach 方法。
forEach 是一个 javascript in build 方法,它类似于 for 循环,但 forEach 只迭代循环开始之前的数组中的元素。
让我们从下面的片段中理解这一点:
array = [1,2,3,4]
for(i=0;i<=array.length;i++){
console.log(array[i]);
array.push(array[i]+1);
}
输出像 1 2 3 4 5 6 ...依此类推(无限),同时每次检查 array.length
让我们检查一下 forEach 方法
array = [1,2,3,4]
array.forEach((element) => {
console.log(element);
array.push(element+1);
})
console.log("array elements after loop",array);
它只处理迭代开始前数组中存在的 4 个元素。
**但是在forEach的情况下,如果我们从数组中弹出元素,它会影响array.length。
举个例子:
array = [1,2,3,4]
array.forEach((element) => {
console.log(element);
array.pop()
})
console.log("array elements after loop",array);
答案 5 :(得分:-1)
以下是针对不同方法的多项性能测试