Why is using “for…in” with array iteration a bad i

2020-01-22 10:12发布

I've been told not to use for...in with arrays in JavaScript. Why not?

27条回答
仙女界的扛把子
2楼-- · 2020-01-22 10:28

Also, due to semantics, the way for, in treats arrays (i.e. the same as any other JavaScript object) is not aligned with other popular languages.

// C#
char[] a = new char[] {'A', 'B', 'C'};
foreach (char x in a) System.Console.Write(x); //Output: "ABC"

// Java
char[] a = {'A', 'B', 'C'};
for (char x : a) System.out.print(x);          //Output: "ABC"

// PHP
$a = array('A', 'B', 'C');
foreach ($a as $x) echo $x;                    //Output: "ABC"

// JavaScript
var a = ['A', 'B', 'C'];
for (var x in a) document.write(x);            //Output: "012"
查看更多
做自己的国王
3楼-- · 2020-01-22 10:28

An important aspect is that for...in only iterates over properties contained in an object which have their enumerable property attribute set to true. So if one attempts to iterate over an object using for...in then arbitrary properties may be missed if their enumerable property attribute is false. It is quite possible to alter the enumerable property attribute for normal Array objects so that certain elements are not enumerated. Though in general the property attributes tend to apply to function properties within an object.

One can check the value of a properties' enumerable property attribute by:

myobject.propertyIsEnumerable('myproperty')

Or to obtain all four property attributes:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

This is a feature available in ECMAScript 5 - in earlier versions it was not possible to alter the value of the enumerable property attribute (it was always set to true).

查看更多
Anthone
4楼-- · 2020-01-22 10:30

You should use the for(var x in y) only on property lists, not on objects (as explained above).

查看更多
Viruses.
5楼-- · 2020-01-22 10:31

In isolation, there is nothing wrong with using for-in on arrays. For-in iterates over the property names of an object, and in the case of an "out-of-the-box" array, the properties corresponds to the array indexes. (The built-in propertes like length, toString and so on are not included in the iteration.)

However, if your code (or the framework you are using) add custom properties to arrays or to the array prototype, then these properties will be included in the iteration, which is probably not what you want.

Some JS frameworks, like Prototype modifies the Array prototype. Other frameworks like JQuery doesn't, so with JQuery you can safely use for-in.

If you are in doubt, you probably shouldn't use for-in.

An alternative way of iterating through an array is using a for-loop:

for (var ix=0;ix<arr.length;ix++) alert(ix);

However, this have a different issue. The issue is that a JavaScript array can have "holes". If you define arr as:

var arr = ["hello"];
arr[100] = "goodbye";

Then the array have two items, but a length of 101. Using for-in will yield two indexes, while the for-loop will yield 101 indexes, where the 99 has a value of undefined.

查看更多
我命由我不由天
6楼-- · 2020-01-22 10:31

Because it will iterate over properties belonging to objects up the prototype chain if you're not careful.

You can use for.. in, just be sure to check each property with hasOwnProperty.

查看更多
SAY GOODBYE
7楼-- · 2020-01-22 10:32

It's not necessarily bad (based on what you're doing), but in the case of arrays, if something has been added to Array.prototype, then you're going to get strange results. Where you'd expect this loop to run three times:

var arr = ['a','b','c'];
for (var key in arr) { ... }

If a function called helpfulUtilityMethod has been added to Array's prototype, then your loop would end up running four times: key would be 0, 1, 2, and helpfulUtilityMethod. If you were only expecting integers, oops.

查看更多
登录 后发表回答