为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript循环:for…in与for

/ 猿问

JavaScript循环:for…in与for

慕沐林林 2019-10-11 10:34:13

我在JavaScript中遇到了奇怪的行为。我懂了


“对象不支持此属性或方法”

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


var buttons = controlDiv.getElementsByTagName("button");

for ( var button in buttons )

    button.removeAttribute('disabled');

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


var buttons = controlDiv.getElementsByTagName("button");

for ( var i = 0; i < buttons.length; i++ )

    buttons[i].removeAttribute('disabled');

buttoninside的值是for...in多少?


查看完整描述

3 回答

?
蝴蝶刀刀

不要for..in用于数组迭代。

重要的是要理解,[]用于访问索引的Javascript数组的方括号语法()实际上是从Object... 继承的。


obj.prop === obj['prop']  // true

该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

}

并且由于数组只是具有顺序数字属性名称(索引)的对象,因此其for..in工作方式类似,因此产生数字索引的方式与生成上面的属性名称的方式相同。


该for..in结构的一个重要特征是,它将继续在原型链中寻找可枚举的属性。它还将迭代继承的可枚举属性。您有责任验证当前属性是否直接存在于本地对象上,而不是它所附加的原型是否存在于本地对象上hasOwnProperty()。


for ( var prop in obj ) {

    if ( obj.hasOwnProperty(prop) ) {

        // prop is actually obj's property (not inherited)

    }

}

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


for..in在Array类型上使用结构的问题在于,无法保证生成属性的顺序...而且通常来说,这是处理数组时极为重要的功能。


另一个问题是它通常比标准for实现慢。


底线

使用a for...in来迭代数组就像使用螺丝刀的but子钉钉子一样...为什么不只使用锤子(for)?


查看完整回答
反对 回复 2019-10-11
?
浮云间

for...in当您要遍历对象的属性时使用。但是它的作用与普通for循环相同:循环变量包含当前的“索引”,表示对象的属性而不是值。


要遍历数组,应使用常规for循环。buttons不是一个数组,而是一个NodeList(类似数组的结构)。


如果迭代buttons与for...in具有:


for(var i in a) {

    console.log(i)

}

您将看到它输出如下内容:


1

2

...

length

item

因为length和item是类型的对象的两个属性NodeList。因此,如果您天真地使用for..in,您将尝试访问buttons['length'].removeAttribute(),这将引发错误,因为buttons['length']它是函数而不是DOM元素。


因此正确的方法是使用普通for循环。但是还有另一个问题:


NodeLists处于活动状态,这意味着每当您访问时length,列表便会更新(再次搜索元素)。因此,您应该避免不必要的呼叫length。


例:


for(var i = 0, l = buttons.length; i < l, i++)


查看完整回答
反对 回复 2019-10-11
?
45度呼吸

尽管for..in通常不应用于数组,但是在ES5之前,有一种将其与稀疏数组一起使用的情况。


如其他答案所述,for..in和Arrays的主要问题是:


属性不一定按顺序返回(即不是0、1、2等)。

返回所有可枚举的属性,包括非索引属性和[[Prototype]]链上的那些属性。这可能导致性能降低,因为可能需要hasOwnProperty测试来避免继承属性。

在ES5之前使用..的原因之一是使用稀疏数组可以提高性能,前提是顺序无关紧要。例如,在下面:


var a = [0];

a[1000] = 1;

遍历一个使用for..in会比使用for循环,因为它不仅可以访问两个属性,而一个for循环将尝试1001快得多。


但是,ES5的forEach使得这种情况变得多余,它仅访问现有的成员,因此:


a.forEach();

还将仅依次迭代两个属性。


查看完整回答
反对 回复 2019-10-11

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信