javascript 每次将 i 与 array.length 进行比较时,循环都会检查 array.length 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8452317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Do loops check the array.length every time when comparing i against array.length?
提问by ajax333221
I was browsing around and I found this:
我四处浏览,发现了这个:
var i, len;
for(i = 0, len = array.length; i < len; i++) {
//...
}
My first thoughts are:
我的第一个想法是:
- Why he did that? (it must be better for some reason)
- Is it worth it? (I assume yes, why else he will do it this way?)
- 他为什么这样做?(由于某种原因它必须更好)
- 这值得么?(我想是的,否则他为什么会这样做?)
Do normal loops (the ones that don't cache the length) check the array.length
each time?
正常循环(不缓存长度的循环)是否array.length
每次都检查?
采纳答案by Rob W
A loop consisting of three parts is executed as follows:
一个由三部分组成的循环执行如下:
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)
So, yes: The .length
property of an array is checked at each enumeration if it's constructed as for(var i=0; i<array.length; i++)
. For micro-optimisation, it's efficient to store the length of an array in a temporary variable (see also: What's the fastest way to loop through an array in JavaScript?).
所以,是的:如果.length
数组构造为for(var i=0; i<array.length; i++)
. 对于微优化,将数组的长度存储在临时变量中是有效的(另请参阅:在 JavaScript 中循环遍历数组的最快方法是什么?)。
Equivalent to for (var i=0; i<array.length; i++) { ... }
:
相当于for (var i=0; i<array.length; i++) { ... }
:
var i = 0;
while (i < array.length) {
...
i++;
}
回答by Fatih Acet
Is it worth it? (obviously yes, why else he will do it this way?)
Absolutely yes. Because, as you say, loop will calculate array length each time. So this will cause an enormous overhead. Run the following code snippets in your firebug or chrome dev tool vs.
绝对没错。因为,正如你所说,循环每次都会计算数组长度。所以这会造成巨大的开销。在您的 firebug 或 chrome 开发工具中运行以下代码片段。
// 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);
Here is the approximate results in various browsers
这是在各种浏览器中的大致结果
Browser optimized unOptimized Firefox 14 26 Chrome 15 32 IE9 22 40 IE8 82 157 IE7 76 148
So consider it again, and use optimized way :)
Note:I tried to work this code on jsPerf but I couldn't access jsPerf now. I guess, it is down when I tried.
所以再考虑一下,并使用优化的方式:)
注意:我试图在 jsPerf 上运行这段代码,但我现在无法访问 jsPerf。我想,当我尝试时它已经关闭了。
回答by Domino
One reason to do this is say, if you're adding elements to the array during the loop but do not want to iterate over them. Say you want to turn [1, 2, 3] into [1, 2, 3, 1, 2, 3]. You could to that with:
这样做的一个原因是,如果您在循环期间向数组添加元素但不想迭代它们。假设你想把 [1, 2, 3] 变成 [1, 2, 3, 1, 2, 3]。你可以这样做:
var initialLength = items.length;
for(var i=0; i<initialLength; ++i) {
items.push(items[i]);
}
If you don't save the length before the loop, then array.length will keep increasing and the loop will run until the browser crashes / kills it.
如果你在循环之前不保存长度,那么 array.length 会不断增加并且循环会一直运行直到浏览器崩溃/杀死它。
Other than that, as the others said, it mildly affects performance. I wouldn't make a habit out of doing this because "premature optimization is the root of all evil". Plus, if you change the size of the array during the loop, doing this could break your code. For instance, if you remove elements from the array during the loop but keep comparing i
to the previous array size, then the loop will try to access elements beyond the new size.
除此之外,正如其他人所说,它会轻微影响性能。我不会养成这样做的习惯,因为“过早的优化是万恶之源”。另外,如果您在循环期间更改数组的大小,这样做可能会破坏您的代码。例如,如果您在循环期间从数组中删除元素,但继续与i
之前的数组大小进行比较,则循环将尝试访问超出新大小的元素。
回答by Jim50
I always thought in JavaScript length was just a property of the array object, pre-calculated by previous array operations - creation, addition, removal - or overridden by the user, so you're just looking up a variable anyway? I must admit I had just assumed that because of the lack of parenthesis, but looking at the MDN page for array.length, it seems to say the same thing.
我一直认为在 JavaScript 中长度只是数组对象的一个属性,由之前的数组操作(创建、添加、删除)预先计算,或者被用户覆盖,所以你只是在查找一个变量?我必须承认,由于缺少括号,我只是假设了这一点,但是查看 MDN 页面的 array.length,它似乎在说同样的事情。
In languages where length is a method or length is calculated by a standard library function, then you should pre-calculate the length before running the loop so The array isn't calculated every iteration, particularly for large datasets. Even then, in modern high level languages like Python, len() just returns the length property of the array object anyway.
在长度是一种方法或长度由标准库函数计算的语言中,您应该在运行循环之前预先计算长度,以便每次迭代都不会计算数组,特别是对于大型数据集。即便如此,在像 Python 这样的现代高级语言中,len() 无论如何也只是返回数组对象的长度属性。
So unless I'm mistaken, the complexity is just O(1), and from that standpoint, even if the variable were slightly faster than a property to lookup each pass, it wouldn't be worth the potential trouble of creating/reusing additional variables outside of the protective for loop scope.
所以除非我弄错了,复杂性只是 O(1),从这个角度来看,即使变量比查找每次通过的属性稍快,也不值得创建/重用额外的潜在麻烦保护性 for 循环范围之外的变量。
However, I suspect that in this case the reason the example's programmer chose this approach is simply just a habit they picked up in another language and carried forwards JavaScript.
但是,我怀疑在这种情况下,示例的程序员选择这种方法的原因仅仅是他们在另一种语言中养成的习惯并继承了 JavaScript。
回答by Mad Man Moon
Here are a number of performance tests for different approaches
以下是针对不同方法的许多性能测试