当迭代字符串或数组(或其他任何带有length属性的东西)时,我总是使用这样的循环:
var foo = [...];
var i;
for(i=0; i<foo.length; i++) {
// do something
}
但是,我刚刚遇到了这样做的人:
var foo = [...];
var fooLen = foo.length;
var i;
for(i=0; i<fooLen; i++) {
// do something
}
他说他认为“.length”正在重新计算长度,因此循环会反复重新计算字符串/数组的长度,因此通过将其长度保存到变量,它将更加优化。
我总是假设长度只是一个值属性,因为它的使用方式(它不是"asdf".length()
,它是"asdf".length
)但是不是这样吗?
答案 0 :(得分:3)
在某些情况下,将长度放入局部变量比访问.length
属性更快,并且它因浏览器而异。在SO和许多jsperf测试中已经就此进行了性能讨论。在现代浏览器中,差异并不像我想象的那么多,但在某些情况下它们确实存在(我似乎无法找到那些先前的线程)。
还有不同类型的对象可能具有不同的性能特征。例如,javascript数组可能具有与从getElementsByClassName()
等某些DOM函数返回的类数组对象不同的性能特征。
并且,在某些情况下,您可能会在数组的末尾添加项目,并且不希望迭代您添加的项目,因此您可以在开始之前获得长度。
答案 1 :(得分:1)
来自MDC
for (var i = 0; i < a.length; i++) {
// Do something with a[i]
}
当您查找length属性时,这效率稍低 每一次循环。这是一个改进:
for (var i = 0, len = a.length; i < len; i++) {
// Do something with a[i]
}
答案 2 :(得分:0)
对于“常规”数组可能没什么区别,但对于像“node.children.length”这样的东西,我会在安全方面犯错,只调用一次。 CoffeeScript会自动为您完成。
请注意,如果长度可以在循环期间发生变化,则行为会有实际差异。
答案 3 :(得分:0)
这取决于你是否改变了foo的长度。
var foo = [1,2,3];
while(foo.length){
foo.shift();
}
显然代码是跟踪foo的长度,而不仅仅是记住一个值。
您可以在循环中将长度指定为数字。
for(i=0, L=foo.length;i<L; i++) {
// do something to foo[i]
}