By lYriCAlsSH


2009-02-01 09:46:38 8 Comments

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

25 comments

@Maher Tliba 2018-05-04 16:10:34

A for...in loop always enumerates the keys. Objects properties keys are always String, even the indexed properties of an array :

var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
  total += elem
}
console.log(total); // 00123

@John Slegers 2016-02-21 20:48:39

I don't think I have much to add to eg. Triptych's answer or CMS's answer on why using for-in should be avoided in some cases.

I do, however, would like to add that in modern browsers there is an alternative to for-in that can be used in those cases where for-in can't be used. That alternative is for-of :

for (var item of items) {
    console.log(item);
}

Note :

Unfortunately, no version of Internet Explorer supports this feature (Edge 12+ does), so you'll have to wait a bit longer until you can use it in your client side production code. However, it should be safe to use in your server side JS code (if you use Node.js).

@georgeawg 2018-07-28 14:19:05

Note: for-in is an ES6 (AKA ECMAScript 2015) statement that iterates over data that iterable objects define to be iterated over. The for...in statement iterates over the enumerable properties of an object, in an arbitrary order.

@Badr Elmers 2018-01-14 01:23:48

Since JavaScript elements are saved as standard object properties, it is not advisable to iterate through JavaScript arrays using for...in loops because normal elements and all enumerable properties will be listed.

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections

@Alireza 2017-12-25 13:38:50

for...in is useful when working on an object in JavaScript, but not for an Array, but still we can not say it's a wrong way, but it's not recommended, look at this example below using for...in loop:

let txt = "";
const person = {fname:"Alireza", lname:"Dezfoolian", age:35}; 
for (const x in person) {
    txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

OK, let's do it with Array now:

let txt = "";
const person = ["Alireza", "Dezfoolian", 35]; 
for (const x in person) {
   txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

As you see the result the same...

But let's try something, let's prototype something to Array...

Array.prototype.someoneelse = "someoneelse";

Now we create a new Array();

let txt = "";
const arr = new Array();
arr[0] = 'Alireza';
arr[1] = 'Dezfoolian';
arr[2] = 35;
for(x in arr) {
 txt += arr[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 someoneelse

You see the someoneelse!!!... We actually looping through new Array object in this case!

So that's one of the reasons why we need to use for..in carefully, but it's not always the case...

@mrmaclean89 2017-09-16 23:19:57

Using the for...in loop for an array is not wrong, although I can guess why someone told you that:

1.) There is already a higher order function, or method, that has that purpose for an array, but has more functionality and leaner syntax, called 'forEach': Array.prototype.forEach(function(element, index, array) {} );

2.) Arrays always have a length, but for...in and forEach do not execute a function for any value that is 'undefined', only for the indexes that have a value defined. So if you only assign one value, these loops will only execute a function once, but since an array is enumerated, it will always have a length up to the highest index that has a defined value, but that length could go unnoticed when using these loops.

3.) The standard for loop will execute a function as many times as you define in the parameters, and since an array is numbered, it makes more sense to define how many times you want to execute a function. Unlike the other loops, the for loop can then execute a function for every index in the array, whether the value is defined or not.

In essence, you can use any loop, but you should remember exactly how they work. Understand the conditions upon which the different loops reiterate, their separate functionalities, and realize they will be more or less appropriate for differing scenarios.

Also, it may be considered a better practice to use the forEach method than the for...in loop in general, because it is easier to write and has more functionality, so you may want to get in the habit of only using this method and standard for, but your call.

See below that the first two loops only execute the console.log statements once, while the standard for loop executes the function as many times as specified, in this case, array.length = 6.

var arr = [];
arr[5] = 'F';

for (var index in arr) {
console.log(index);
console.log(arr[index]);
console.log(arr)
}
// 5
// 'F'
// => (6) [undefined x 5, 6]

arr.forEach(function(element, index, arr) {
console.log(index);
console.log(element);
console.log(arr);
});
// 5
// 'F'
// => Array (6) [undefined x 5, 6]

for (var index = 0; index < arr.length; index++) {
console.log(index);
console.log(arr[index]);
console.log(arr);
};
// 0
// undefined
// => Array (6) [undefined x 5, 6]

// 1
// undefined
// => Array (6) [undefined x 5, 6]

// 2
// undefined
// => Array (6) [undefined x 5, 6]

// 3
// undefined
// => Array (6) [undefined x 5, 6]

// 4
// undefined
// => Array (6) [undefined x 5, 6]

// 5
// 'F'
// => Array (6) [undefined x 5, 6]

@Triptych 2009-02-01 10:08:34

The reason is that one construct:

var a = []; // Create a new empty array.
a[5] = 5;   // Perfectly legal JavaScript that resizes the array.

for (var i = 0; i < a.length; i++) {
    // Iterate over numeric indexes from 0 to 5, as everyone expects.
    console.log(a[i]);
}

/* Will display:
   undefined
   undefined
   undefined
   undefined
   undefined
   5
*/

can sometimes be totally different from the other:

var a = [];
a[5] = 5;
for (var x in a) {
    // Shows only the explicitly set index of "5", and ignores 0-4
    console.log(x);
}

/* Will display:
   5
*/

Also consider that JavaScript libraries might do things like this, which will affect any array you create:

// Somewhere deep in your JavaScript library...
Array.prototype.foo = 1;

// Now you have no idea what the below code will do.
var a = [1, 2, 3, 4, 5];
for (var x in a){
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x'.
    console.log(x);
}

/* Will display:
   0
   1
   2
   3
   4
   foo
*/

@bobince 2009-02-01 12:14:43

Historically, some browsers even iterated over 'length', 'toString' etc.!

@Chris Morgan 2010-11-25 02:24:02

Remember to use (var x in a) rather than (x in a) - don't want to create a global.

@Stewart 2011-03-01 00:52:39

First issue isn't a reason it's bad, only a difference in semantics. Second issue seems to me a reason (on top of clashes between libraries doing the same) that altering the prototype of a built-in datatype is bad, rather than that for..in is bad.

@Triptych 2011-03-01 07:55:19

@Stewart. The 'difference in semantics' is actually a flaw in Javascript. The broken semantics mean the code doesn't do what you think it will, and that's why the construct is typically avoided.

@Stewart 2011-03-01 10:29:23

Arrays in JS are associative - they just can be used as linear arrays. As such, the whole point of using for..in is to iterate over the array's keys, whatever they may be.

@Martijn 2011-03-01 15:15:05

@Stewart: All objects in JS are associative. A JS Array is an object, so yes, it’s associative too, but that’s not what it’s for. If you want to iterate over an object's keys, use for (var key in object). If you want to iterate over an array’s elements, however, use for(var i = 0; i < array.length; i += 1).

@Tim Goodman 2011-03-01 19:58:52

I corrected for(int i=0 to for(var i=0. The first version produces a not-very-helpful "missing semi-colon" error (at least in Firefox).

@Stewart 2011-03-18 11:15:29

So using built-in arrays as associative arrays is abusing the JS object model? Is there any official recommendation on what to use for AAs instead?

@stivlo 2011-10-22 10:53:07

You said for the first example, that it Iterates over numeric indexes from 0 to 4, as everyone expects, I expect it to iterate from 0 to 5! Since if you add an element in position 5, the array will have 6 elements (5 of them undefined).

@user1086498 2012-02-20 23:13:53

This overall presents a problem in javascript, since the point of something like for..in is to be key-agnostic on objects or arrays. Quite the opposite, if you add something to array[5] you expect the array to have one item, with key 5, not five blank items that you didn't insert. You expect there to be in the array what you put in it! Unless you told the array explicitly to have five items, key '5' realistically should not indicate the number of items in the array. But this relates to what an array represents; in JSON arrays do not really have keys; to use the term key is misleading.

@nnnnnn 2012-08-30 05:37:07

@stivlo - if you add an element only in position 5, the array will have 1 element as the for..in loop shows. There's a difference between an element that doesn't exist and so returns undefined when you try to access it and an element that does exist and returns undefined because that value has been explicitly assigned.

@metamatt 2012-12-03 23:56:05

I think the examples would be even clearer if you set a[5] to something other than 5, say, a[5]=42. The fact that the second example ("for (x in a)" only enumerates one value is not surprising to me; the fact that the value it enumerates is 5 instead of 42 is surprising to me (coming from other languages with a similar construct that enumerates list contents instead of array indices).

@August 2013-03-22 16:45:21

In the first example.. Would it be more efficient to call a.length only once (and set to a var) prior to the loop? vs each time the loop iterates?

@Triptych 2013-03-23 04:21:25

Augustum - yes, it would be more efficient. But it would also be more code, and would therefore illustrate the concept under question less directly.

@Lior 2014-02-04 16:57:12

You missed out on the fact it won't iterate in the right order: stackoverflow.com/a/21558566/1233630

@Qwerty 2014-03-03 20:05:26

Object.keys(a).forEach( function(item) { console.log(item) } ) takes only real attributes, not those set in prototype.

@chuck258 2015-08-26 06:24:07

@Martijin: Instead of the rather long and verbose for(var i = 0; i < array.length; i += 1) pattern, there is a new for let value of object function in the ES6 standard which is already supported in most modern browsers See the MDN page

@Atul Agrawal 2016-10-24 14:25:27

sometimes might return function as last value

@MKPS 2017-05-06 23:15:53

Under first example, in output part (Will display:), missed one undefined. Correct 5, not 4 undefined-s, I belive. P.s. I can't edit posts.

@KnowGe 2017-07-21 19:21:53

I respect you my friend. You saved me at 10 PM after one week digging everything. Really thank you !!!

@Jonathan002 2017-11-08 12:51:20

Why doesn't the for...in iterate over all standard prototypes instead of just new prototype created like foo?

@Redu 2017-01-28 08:16:02

TL&DR: Using the for in loop in arrays is not evil, in fact quite the opposite.

I think the for in loop is a gem of JS if used correctly in arrays. You are expected to have full control over your software and know what you are doing. Let's see the mentioned drawbacks and disprove them one by one.

  1. It loops through inherited properties as well: First of all any extensions to the Array.prototype should have been done by using Object.defineProperty() and their enumerable descriptor should be set to false. Any library not doing so should not be used at all.
  2. Properties those you add to the inheritance chain later get counted: When doing array sub-classing by Object.setPrototypeOf or by Class extend. You should again use Object.defineProperty() which by default sets the writable, enumerable and configurable property descriptors to false. Lets see an array sub-classing example here...

function Stack(...a){
  var stack = new Array(...a);
  Object.setPrototypeOf(stack, Stack.prototype);
  return stack;
}
Stack.prototype = Object.create(Array.prototype);                                 // now stack has full access to array methods.
Object.defineProperty(Stack.prototype,"constructor",{value:Stack});               // now Stack is a proper constructor
Object.defineProperty(Stack.prototype,"peak",{value: function(){                  // add Stack "only" methods to the Stack.prototype.
                                                       return this[this.length-1];
                                                     }
                                             });
var s = new Stack(1,2,3,4,1);
console.log(s.peak());
s[s.length] = 7;
console.log("length:",s.length);
s.push(42);
console.log(JSON.stringify(s));
console.log("length:",s.length);

for(var i in s) console.log(s[i]);

So you see.. for in loop is now safe since you cared about your code.

  1. The for in loop is slow: Hell no. It's by far the fastest method of iteration if you are looping over sparse arrays which are needed time to time. This is one of the most important performance tricks that one should know. Let's see an example. We will loop over a sparse array.

var a = [];
a[0] = "zero";
a[10000000] = "ten million";
console.time("for loop on array a:");
for(var i=0; i < a.length; i++) a[i] && console.log(a[i]);
console.timeEnd("for loop on array a:");
console.time("for in loop on array a:");
for(var i in a) a[i] && console.log(a[i]);
console.timeEnd("for in loop on array a:");

@Ravi Shanker Reddy 2017-03-17 14:08:41

Can you explain this please jsben.ch/#/BQhED

@Redu 2017-03-17 15:05:35

@Ravi Shanker Reddy Good benchmarking set up. As I have mentioned in my answer the for in loop outshines the others "if" the array is sparse and the more if it gets the bigger in size. So i have rearranged the bench test for a sparse array, arr, of size ~10000 with only 50 items randomly chosen among [42,"test",{t:1},null, void 0] at random indices. You will immediately notice the difference. -->> Check it up here <<--.

@binaryfunt 2017-08-24 17:20:49

The sparse array point is a good one

@Pim Jager 2009-02-01 10:08:37

Because for...in enumerates through the object that holds the array, not the array itself. If I add a function to the arrays prototype chain, that will also be included. I.e.

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}

This will write:

0 = foo
1 = bar
myOwnFunction = function() { alert(this); }

And since you can never be sure that nothing will be added to the prototype chain just use a for loop to enumerate the array:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

This will write:

0 = foo
1 = bar

@RobG 2013-10-22 22:28:47

Arrays are Objects, there is no "object that holds the array".

@cHao 2012-05-14 16:26:20

Aside from the fact that for...in loops over all enumerable properties (which is not the same as "all array elements"!), see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf, section 12.6.4 (5th edition) or 13.7.5.15 (7th edition):

The mechanics and order of enumerating the properties ... is not specified...

(Emphasis mine.)

That means if a browser wanted to, it could go through the properties in the order in which they were inserted. Or in numerical order. Or in lexical order (where "30" comes before "4"! Keep in mind all object keys -- and thus, all array indexes -- are actually strings, so that makes total sense). It could go through them by bucket, if it implemented objects as hash tables. Or take any of that and add "backwards". A browser could even iterate randomly and be ECMA-262 compliant, as long as it visited each property exactly once.

In practice, most browsers currently like to iterate in roughly the same order. But there's nothing saying they have to. That's implementation specific, and could change at any time if another way was found to be far more efficient.

Either way, for...in carries with it no connotation of order. If you care about order, be explicit about it and use a regular for loop with an index.

@MarcG 2016-03-10 04:29:37

As of 2016 (ES6) we may use for…of for array iteration, as John Slegers already noticed.

I would just like to add this simple demonstration code, to make things clearer:

Array.prototype.foo = 1;
var arr = [];
arr[5] = "xyz";

console.log("for...of:");
var count = 0;
for (var item of arr) {
    console.log(count + ":", item);
    count++;
    }

console.log("for...in:");
count = 0;
for (var item in arr) {
    console.log(count + ":", item);
    count++;
    }

The console shows:

for...of:

0: undefined
1: undefined
2: undefined
3: undefined
4: undefined
5: xyz

for...in:

0: 5
1: foo

In other words:

  • for...of counts from 0 to 5, and also ignores Array.prototype.foo. It shows array values.

  • for...in lists only the 5, ignoring undefined array indexes, but adding foo. It shows array property names.

@CMS 2010-11-23 21:22:54

The for-in statement by itself is not a "bad practice", however it can be mis-used, for example, to iterate over arrays or array-like objects.

The purpose of the for-in statement is to enumerate over object properties. This statement will go up in the prototype chain, also enumerating over inherited properties, a thing that sometimes is not desired.

Also, the order of iteration is not guaranteed by the spec., meaning that if you want to "iterate" an array object, with this statement you cannot be sure that the properties (array indexes) will be visited in the numeric order.

For example, in JScript (IE <= 8), the order of enumeration even on Array objects is defined as the properties were created:

var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';

for (var p in array) {
  //... p will be "2", "1" and "0" on IE
}

Also, speaking about inherited properties, if you, for example, extend the Array.prototype object (like some libraries as MooTools do), that properties will be also enumerated:

Array.prototype.last = function () { return this[this.length-1]; };

for (var p in []) { // an empty array
  // last will be enumerated
}

As I said before to iterate over arrays or array-like objects, the best thing is to use a sequential loop, such as a plain-old for/while loop.

When you want to enumerate only the own properties of an object (the ones that aren't inherited), you can use the hasOwnProperty method:

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

And some people even recommend calling the method directly from Object.prototype to avoid having problems if somebody adds a property named hasOwnProperty to our object:

for (var prop in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
    // prop is not inherited
  }
}

@Chris Morgan 2010-11-25 02:25:41

See also David Humphrey's post Iterating over Objects in JavaScript Quickly - for array's for..in is much slower than "normal" loops.

@Scott Rippey 2011-01-14 00:08:10

Question about the last point about "hasOwnProperty": If someone overrides "hasOwnProperty" on an object, you'll have problems. But won't you have the same problems if someone overrides "Object.prototype.hasOwnProperty"? Either way they're screwing you up and it's not your responsibility right?

@rjmunro 2013-07-03 12:05:37

You say for..in is not bad practice, but it can be misused. Have you got a real world example of good practice, where you really did want to go through all of an objects properties including inherited properties?

@Nathan Wall 2014-05-29 15:24:17

@ScottRippey: If you want to take it there: youtube.com/watch?v=FrFUI591WhI

@equiman 2017-04-20 13:08:36

with this answer I found that can access the value with for (var p in array) { array[p]; }

@Pointy 2010-11-23 21:23:50

The problem with for ... in ... — and this only becomes a problem when a programmer doesn't really understand the language; it's not really a bug or anything — is that it iterates over all members of an object (well, all enumerable members, but that's a detail for now). When you want to iterate over just the indexed properties of an array, the only guaranteed way to keep things semantically consistent is to use an integer index (that is, a for (var i = 0; i < array.length; ++i) style loop).

Any object can have arbitrary properties associated with it. There would be nothing terrible about loading additional properties onto an array instance, in particular. Code that wants to see only indexed array-like properties therefore must stick to an integer index. Code that is fully aware of what for ... in does and really need to see all properties, well then that's ok too.

@NiCk Newman 2015-07-31 16:20:58

Nice explanation Pointy. Just curious. If I had an array that was inside an object under multiply properties and did for in, as compared to a regular for loop, those arrays would get iterated over? (which would in essence, slow performance, right?)

@Pointy 2015-07-31 18:42:31

@NiCkNewman well the object you reference after in in a for ... in loop will just

@NiCk Newman 2015-07-31 19:24:18

I see. Just curious because I have objects and arrays inside my main game object and was wondering if for inning that would be more painful then simply a regular for loop on the indexes.

@Pointy 2015-07-31 20:15:56

@NiCkNewman well the theme of this whole question is that you just should not use for ... in on arrays; there are many good reasons not to. It's no so much a performance issue as a "make sure it doesn't break" issue.

@NiCk Newman 2015-07-31 22:05:07

Well, my objects are stored in an array technically, that's why I was worried, something like: [{a:'hey',b:'hi'},{a:'hey',b:'hi'}], but yea, I understand.

@JacquesB 2009-02-01 10:34:57

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.

@Lior 2014-02-04 16:54:16

Mainly two reasons:

One

Like others have said, You might get keys which aren't in your array or that are inherited from the prototype. So if, let's say, a library adds a property to the Array or Object prototypes:

Array.prototype.someProperty = true

You'll get it as part of every array:

for(var item in [1,2,3]){
  console.log(item) // will log 1,2,3 but also "someProperty"
}

you could solve this with the hasOwnProperty method:

var ary = [1,2,3];
for(var item in ary){
   if(ary.hasOwnProperty(item)){
      console.log(item) // will log only 1,2,3
   }
}

but this is true for iterating over any object with a for-in loop.

Two

Usually the order of the items in an array is important, but the for-in loop won't necessarily iterate in the right order, that's because it treats the array as an object, which is the way it is implemented in JS, and not as an array. This seems like a small thing, but it can really screw up applications and is hard to debug.

@Qwerty 2014-03-03 20:06:55

Object.keys(a).forEach( function(item) { console.log(item) } ) iterate over an array of own property keys, not those inherited from prototype.

@Lior 2014-03-06 10:59:41

True, but like the for-in loop, it won't necessarily be in the right index order. Also, it won't work on older browsers not supporting ES5.

@Qwerty 2014-03-21 16:02:12

You can teach those browsers array.forEach by inserting certain code in your scripts. See Polyfill developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

@Lior 2014-03-23 09:22:36

Of course, but then you are manipulating the prototype, and that is not always a good idea...and still, you have the issue of the order...

@a better oliver 2015-07-05 11:15:57

And, of course, reason number three: Sparse arrays.

@matpop 2013-10-25 16:43:32

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"

@Ricardo 2010-11-23 21:44:27

The for/in works with two types of variables: hashtables (associative arrays) and array (non-associative).

JavaScript will automatically determine the way its passes through the items. So if you know that your array is really non-associative you can use for (var i=0; i<=arrayLen; i++), and skip the auto-detection iteration.

But in my opinion, it's better to use for/in, the process required for that auto-detection is very small.

A real answer for this will depend on how the browser parsers/interpret the JavaScript code. It can change between browsers.

I can't think of other purposes to not using for/in;

//Non-associative
var arr = ['a', 'b', 'c'];
for (var i in arr)
   alert(arr[i]);

//Associative
var arr = {
   item1 : 'a',
   item2 : 'b',
   item3 : 'c'
};

for (var i in arr)
   alert(arr[i]);

@Ricardo 2010-11-23 21:49:02

true, unless you are using prototyped objects. ;) below

@Free Consulting 2010-11-25 00:56:24

Thats because Array is Object too

@a better oliver 2015-07-05 11:12:02

for ... in works with objects. There's no such thing as auto-detection.

@WynandB 2013-03-14 07:12:23

Short answer: It's just not worth it.


Longer answer: It's just not worth it, even if sequential element order and optimal performance aren't required.


Long answer: It's just not worth it, for reasons following:

  • Using for (var i in array) {} will cause 'array' to be interpreted as any other pure object, traversing the object property chain and ultimately performing slower than an index-based for loop.
  • It's not guaranteed to return the object properties in sequential order as one might expect.
  • Using hasOwnProperty() or isNaN() checks to filter the object properties is an additional overhead causing it to perform (even more) slower. Also, introducing such additional logic negates the key reason for using it in the first place, i.e. because of the more concise format.

For these reasons an acceptable trade-off between performance and convenience doesn't even exist. Really, there's no benefit unless the intent is to treat the array as a pure object and performs operations on the array object's properties.

@Pierz 2013-05-10 18:20:26

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

@dc1 2012-06-05 22:52:52

In addition to the other problems, the "for..in" syntax is probably slower, because the index is a string, not an integer.

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'

@cHao 2012-06-06 02:50:14

Probably doesn't matter a whole lot. Array elements are properties of an Array-based or Array-like object, and all object properties have string keys. Unless your JS engine somehow optimizes it, even if you used a number it'd end up being turned into a string for the lookup.

@szmoore 2014-02-14 03:28:36

Regardless of any performance issues, if you are new to JavaScript, use var i in a and expect the index to be an integer, then doing something like a[i+offset] = <value> will be putting values in completely the wrong places. ("1" + 1 == "11").

@user268396 2010-11-23 21:25:10

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

@JAL 2010-11-24 06:48:17

Just a note about SO - there is no 'above' because comments change order on the page all the time. So, we don't really know which comment you mean. It's good to say "in x person's comment" for this reason.

@WynandB 2013-03-14 01:01:19

@JAL ...or add the permalink to the answer.

@josh3736 2010-11-23 21:25:07

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.

@JAL 2010-11-23 21:20:54

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.

@Pointy 2010-11-23 21:27:45

Not enough - it's perfectly OK to add arbitrary named properties to array instances, and those will test true from hasOwnProperty() checks.

@JAL 2010-11-23 23:49:35

Good point, thanks. I've never been silly enough to do that to an Array myself, so I haven't considered that!

@WynandB 2013-03-14 00:33:24

@Pointy I haven't tested this, but perhaps this can be overcome by using an isNaN check on each property name.

@Pointy 2013-03-14 04:34:11

@Wynand interesting idea; however I don't really see why it's worth the trouble when iterating with a simple numeric index is so easy.

@doldt 2015-04-29 14:21:30

@WynandB sorry for the bump, but I feel a correction is in order: isNaN is for checking whether a variable is the special value NaN or not, it cannot be used to check for 'things other than numbers' (you can go with a regular typeof for that).

@ctmiddle 2009-09-02 02:29:46

In addition to the reasons given in other answers, you may not want to use the "for...in" structure if you need to do math with the counter variable because the loop iterates through the names of the object's properties and so the variable is a string.

For example,

for (var i=0; i<a.length; i++) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

will write

0, number, 1
1, number, 2
...

whereas,

for (var ii in a) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

will write

0, string, 01
1, string, 11
...

Of course, this can easily be overcome by including

ii = parseInt(ii);

in the loop, but the first structure is more direct.

@Konrad Borowski 2012-04-24 17:19:43

You can use prefix + instead of parseInt unless you really need integer or ignore invalid characters.

@Derek 朕會功夫 2012-07-05 23:21:00

Also, using parseInt() is not recommended. Try parseInt("025"); and it will fail.

@IAmTimCorey 2013-04-16 14:45:53

@Derek朕會功夫 - you can definitely use parseInt. The issue is if you don't include the radix, older browsers might try to interpret the number (thus 025 becomes octal). This was fixed in ECMAScript 5 but it still happens for numbers starting with "0x" (it interprets the number as hex). To be on the safe side, use the radix to specify the number like so parseInt("025", 10) - that specifies base 10.

@Christoph 2009-02-01 14:04:57

There are three reasons why you shouldn't use for..in to iterate over array elements:

  • for..in will loop over all own and inherited properties of the array object which aren't DontEnum; that means if someone adds properties to the specific array object (there are valid reasons for this - I've done so myself) or changed Array.prototype (which is considered bad practice in code which is supposed to work well with other scripts), these properties will be iterated over as well; inherited properties can be excluded by checking hasOwnProperty(), but that won't help you with properties set in the array object itself

  • for..in isn't guaranteed to preserve element ordering

  • it's slow because you have to walk all properties of the array object and its whole prototype chain and will still only get the property's name, ie to get the value, an additional lookup will be required

@vava 2009-02-01 09:50:03

Because it enumerates through object fields, not indexes. You can get value with index "length" and I doubt you want this.

@lYriCAlsSH 2009-02-01 09:57:22

So whats the best way of doing that?

@vava 2009-02-01 10:08:17

for (var i = 0; i < arr.length; i++) {}

@vava 2009-02-01 10:09:32

In firefox 3 you could also use either arr.forEach or for(var [i, v] in Iterator(arr)) {} but neither of those works in IE, although you can write forEach method yourself.

@vava 2009-02-01 10:14:06

and virtually every library has it's own method for this too.

@JacquesB 2009-02-01 10:59:17

This answer is wrong. "lenght" will not be included in for-in iteration. It is only properties you add yourself which is included.

Related Questions

Sponsored Content

34 Answered Questions

[SOLVED] var functionName = function() {} vs function functionName() {}

69 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5130906 View
  • 6428 Score
  • 69 Answer
  • Tags:   javascript arrays

88 Answered Questions

[SOLVED] How do JavaScript closures work?

42 Answered Questions

[SOLVED] How do I check if an array includes an object in JavaScript?

28 Answered Questions

[SOLVED] For-each over an array in JavaScript?

38 Answered Questions

[SOLVED] Loop through an array in JavaScript

25 Answered Questions

31 Answered Questions

[SOLVED] How to append something to an array?

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

7 Answered Questions

[SOLVED] Iterate through a HashMap

Sponsored Content