JavaScript 循环:for...in 与 for

发布于 2024-10-21 01:19:27 字数 551 浏览 3 评论 0原文

我在 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');

for.properties 中的 button 的值是多少? ..在

I faced a strange behaviour in Javascript. I get

"Object doesn't support this property or method"

exception for the removeAttribute function in the following code:

var buttons = controlDiv.getElementsByTagName("button");
for ( var button in buttons )
    button.removeAttribute('disabled');

When I change the code with the following, the problem disappears:

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

What is the value of button inside the for...in?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朱染 2024-10-28 01:19:32

虽然 for..in 通常不应该用于数组,但是在 ES5 之前,存在将其与稀疏数组一起使用的情况。

正如其他答案中所述,for..in 和数组的主要问题是:

  1. 属性不一定按顺序返回(即不是 0、1、2 等)。
  2. 返回所有可枚举属性,包括非索引属性和[[Prototype]] 链上的那些。这会导致性能降低,因为可能需要进行 hasOwnProperty 测试以避免继承属性。

在 ES5 之前使用 for..in 的原因之一是提高稀疏数组的性能(只要顺序无关紧要)。例如,在下面的例子中:

var a = [0];
a[1000] = 1;

使用 for..in 迭代a将比使用 for 循环快得多,因为它只会访问两个属性,而 for 循环将尝试 1001。

但是,这个ES5 的 forEach 使 case 变得多余,它只访问存在的成员,因此:

a.forEach();

也只会按顺序迭代两个属性。

While for..in should not generally be used for Arrays, however prior to ES5 there was a case for using it with sparse arrays.

As noted in other answers, the primary issues with for..in and Arrays are:

  1. The properties are not necessarily returned in order (i.e. not 0, 1, 2 etc.)
  2. All enumerable properties are returned, including the non–index properties and those on the [[Prototype]] chain. This leads to lower performance as a hasOwnProperty test is probably required to avoid inherited properties.

One reason to use for..in prior to ES5 was to improve performance with sparse arrays, provided order doesn't matter. For example, in the following:

var a = [0];
a[1000] = 1;

Iterating over a using for..in will be much faster than using a for loop, as it will only visit two properties whereas a for loop will try 1001.

However, this case is made redundant by ES5's forEach, which only visits members that exist, so:

a.forEach();

will also only iterate over two properties, in order.

世界等同你 2024-10-28 01:19:31

for...in 用于循环访问对象的属性。但它的工作方式与普通的 for 循环相同:循环变量包含当前的“索引”,即对象的属性而不是值。

要迭代数组,您应该使用普通的 for 循环。 buttons 不是一个数组,而是一个 NodeList (类似数组的结构)。

如果使用 for...in 迭代 buttons with:

for(var i in a) {
    console.log(i)
}

您将看到它输出类似以下内容:

1
2
...
length
item

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

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

NodeList 是实时的,这意味着每当您访问 length 时,列表都会更新(再次搜索元素)。因此,您应该避免不必要地调用 length

例子:

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

for...in is to be used when you want to loop over the properties of an object. But it works the same as a normal for loop: The loop variable contains the current "index", meaning the property of the object and not the value.

To iterate over arrays, you should use a normal for loop. buttons is not an array but a NodeList (an array like structure).

If iterate over buttons with for...in with:

for(var i in a) {
    console.log(i)
}

You will see that it output something like:

1
2
...
length
item

because length and item are two properties of an object of type NodeList. So if you'd naively use for..in, you would try to access buttons['length'].removeAttribute() which will throw an error as buttons['length'] is a function and not a DOM element.

So the correct way is to use a normal for loop. But there is another issue:

NodeLists are live, meaning whenever you access e.g. length, the list is updated (the elements are searched again). Therefore you should avoid unnecessary calls to length.

Example:

for(var i = 0, l = buttons.length; i < l, i++)
北凤男飞 2024-10-28 01:19:31

for(var key in obj) { } 迭代对象中的所有元素,包括其原型的元素。
因此,如果您正在使用它并且不知道任何扩展的Object.prototype,您应该始终测试obj.hasOwnProperty(key),如果此检查返回 false,则跳过该键。

for(start; continuation;loop) 是一个 C 风格的循环:start 在循环之前执行,continuation 被测试并且仅循环当 true 时继续,loop 在每个循环后执行。

for(var key in obj) { } iterates over all elements in the object, including those of its prototypes.
So if you are using it and cannot know nothing extended Object.prototype you should always test obj.hasOwnProperty(key) and skip the key if this check returns false.

for(start; continuation; loop) is a C-style loop: start is executed before the loop, continuation is tested and the loop only continues while it's true, loop is executed after every loop.

夏至、离别 2024-10-28 01:19:30

不要使用 for..in 进行数组迭代。

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

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

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

Javascript 的 for..in 旨在迭代对象的属性。生成每个属性的密钥。使用此对象的括号语法相结合,您可以轻松访问所需的值。

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)
    }
}

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

在 Array 类型上使用 for..in 结构的问题在于,没有保证属性的生成顺序......一般来说,这是处理数组时非常重要的功能。

另一个问题是它通常慢于标准for 实施。

底线

使用 for...in 来迭代数组就像使用螺丝刀的刀柄来钉钉子...为什么不直接使用锤子 (for< /代码>)?

Don't use for..in for Array iteration.

It's important to understand that Javascript Array's square bracket syntax ([]) for accessing indicies is actually inherited from the Object...

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

The for..in structure does not work like a more traditional for..each/in that would be found in other languages (php, python, etc...).

Javascript's for..in is designed to iterate over the properties of an object. Producing the key of each property. Using this key combined with the Object's bracket syntax, you can easily access the values you are after.

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
}

And because the Array is simply an Object with sequential numeric property names (indexes) the for..in works in a similar way, producing the numeric indicies just as it produces the property names above.

An important characteristic of the for..in structure is that it continues to search for enumerable properties up the prototype chain. It will also iterate inherited enumerable properties. It is up to you to verify that the current property exists directly on the local object and not the prototype it is attached to with hasOwnProperty()...

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

(More on Prototypal Inheritance)

The problem with using the for..in structure on the Array type is that there is no garauntee as to what order the properties are produced... and generally speaking that is a farily important feature in processing an array.

Another problem is that it usually slower than a standard for implementation.

Bottom Line

Using a for...in to iterate arrays is like using the butt of a screw driver to drive a nail... why wouldn't you just use a hammer (for)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文