JavaScript循环:for ... in vs for

Fey*_*yaz 13 javascript arrays for-loop for-in-loop

我在Javascript中遇到了一个奇怪的行为.我明白了

"对象不支持此属性或方法"

removeAttribute以下代码中的函数异常:

var buttons = controlDiv.getElementsByTagName("button");
for ( var button in buttons )
    button.removeAttribute('disabled');
Run Code Online (Sandbox Code Playgroud)

当我用以下代码更改代码时,问题消失了:

var buttons = controlDiv.getElementsByTagName("button");
for ( var i = 0; i < buttons.length; i++ )
    buttons[i].removeAttribute('disabled');
Run Code Online (Sandbox Code Playgroud)

button里面有for...in什么价值?

jon*_*ohn 46

不要for..in用于Array迭代.

重要的是要理解[]用于访问指标的Javascript Array的方括号语法()实际上是从Object... 继承的.

obj.prop === obj['prop']  // true
Run Code Online (Sandbox Code Playgroud)

for..in结构不像for..each/in其他语言(php,python等)中更传统的工作.

Javascript for..in旨在迭代对象的属性.生成每个属性的关键.使用此Object括号语法,您可以轻松访问您所追求的值.

var obj = {
    foo: "bar",
    fizz: "buzz",
    moo: "muck"
};

for ( var prop in obj ) {
    console.log(prop);      // foo / fizz / moo
    console.log(obj[prop]); // bar / buzz / muck
}
Run Code Online (Sandbox Code Playgroud)

而且因为数组是简单地用一个对象连续的数字属性名(索引)for..in以类似的方式工作,生产只是因为它产生的上述属性名称数字indicies.

for..in结构的一个重要特征是它继续在原型链上搜索可枚举的属性.它还将迭代继承的可枚举属性.由您来验证当前属性是否直接存在于本地对象上,而不是它附加到的原型hasOwnProperty()...

for ( var prop in obj ) {
    if ( obj.hasOwnProperty(prop) ) {
        // prop is actually obj's property (not inherited)
    }
}
Run Code Online (Sandbox Code Playgroud)

(有关原型继承的更多信息)

for..in在Array类型上使用结构的问题在于没有关于属性生成顺序的重要信息......一般来说,这是处理数组的一个非常重要的特性.

另一个问题是它通常标准for实现.

底线

使用a for...in来迭代数组就像使用螺丝刀的屁股来驱动钉子......你为什么不用锤子(for)?

  • 这是正确的,但还有另一个原因可以避免对数组使用`for ... in`.[来自MDC](https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in):_... for ... in语句将返回用户定义的名称属性以及数字索引...._ (4认同)

Fel*_*ing 7

for...in要在循环对象的属性时使用.但它与普通for循环的工作方式相同:循环变量包含当前的"索引",表示对象的属性而不是值.

要迭代数组,您应该使用普通for循环.buttons不是数组而是NodeList(数组结构).

如果迭代buttonsfor...in具有:

for(var i in a) {
    console.log(i)
}
Run Code Online (Sandbox Code Playgroud)

你会看到它输出如下:

1
2
...
length
item
Run Code Online (Sandbox Code Playgroud)

因为lengthitem是类型对象的两个属性NodeList.因此,如果你天真地使用for..in,你会尝试访问buttons['length'].removeAttribute()哪个会抛出错误,因为它buttons['length']是一个函数,而不是一个DOM元素.

所以正确的方法是使用正常for循环.但还有另一个问题:

NodeLists是实时的,意味着无论何时访问,例如length,列表都会更新(再次搜索元素).因此,您应该避免不必要的调用length.

例:

for(var i = 0, l = buttons.length; i < l, i++)
Run Code Online (Sandbox Code Playgroud)

  • 为了避免调用长度,我更喜欢`for(var i = 0; i in buttons; i ++)`.我喜欢这种检查的明确程度,而不是隐式检查长度. (2认同)