Just started learning Javascript. Recently I used a for-in loops to iterate over properties of an object. For example...
var someObject = { a:1, b:2 };
for(var property in someObject){
console.log(property);
}
This would print...
"a"
"b"
However, when I use it to iterate over an array...
var someArray = ["a","b","c"];
for(var element in someObject){
console.log(element);
}
The indices, rather than the elements, get printed...
"0"
"1"
"2"
Why is this the case? In general, do JS for-in loops print properties only when iterated over objects and indices for everything else?
If it prints indices with the exception of objects, why would one ever use a classic for loop such as
for(var i=0,i<someNumber,i++)
when one can just use a for in loop? Especially since this seems a lot more concise?
for(var i in something)
Am I even supposed to use for-in loops for anything besides objects?
Thanks!
Quoting from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Description
for..in should not be used to iterate over an Array where index order
is important. Array indexes are just enumerable properties with
integer names and are otherwise identical to general Object
properties. There is no guarantee that for...in will return the
indexes in any particular order and it will return all enumerable
properties, including those with non–integer names and those that are
inherited.
Because the order of iteration is implementation dependent, iterating
over an array may not visit elements in a consistent order. Therefore
it is better to use a for loop with a numeric index (or Array.forEach
or the non-standard for...of loop) when iterating over arrays where
the order of access is important.
So, Don't rely on for..in for iterating over an Array.
And to answer
The indices, rather than the elements, get printed... Why is this the
case?
The answer has already been quoted above.
Array indexes are just enumerable properties with integer names and
are otherwise identical to general Object properties.
To confirm that fact, try the following sample code
var myArray = ["A", "B", "C"];
for (var i = 0; i < 3; i += 1) {
console.log(myArray.hasOwnProperty(i)); // will print true
}
That is why for..in works with Arrays as well.
Related
As the defination says for-in loop is used to loop through the properties of an object ,than why is it looping the element of an array?
var arr = ['a','b','c'], indexes = [];
Array.prototype.each = function() {/*blah*/};
for (var index in arr) {
indexes.push(index);
}
indexes; //["0", "1", "2", "each"]
why are 0,1,2 enumerated?They are not the properties
Quote from the documentation:
for..in should not be used to iterate over an Array where index order
is important. Array indexes are just enumerable properties with
integer names and are otherwise identical to general Object
properties. There is no guarantee that for...in will return the
indexes in any particular order and it will return all enumerable
properties, including those with non–integer names and those that are
inherited.
Because the order of iteration is implementation dependent, iterating
over an array may not visit elements in a consistent order. Therefore
it is better to use a for loop with a numeric index (or Array.forEach
or the non-standard for...of loop) when iterating over arrays where
the order of access is important.
The key here holding the answer to your question is the following sentence:
Array indexes are just enumerable properties with integer names and
are otherwise identical to general Object properties.
And the following sentence sums it up:
for..in should not be used to iterate over an Array where index order
is important.
Each index in the array for which the array has an element is a property of that array. So this is basically what your array looks like behind the scenes:
>>> arr
{
0: 'a',
1: 'b',
2: 'c',
'each': function() {}
'length': 3
};
These keys are enumerable which is the reason why you're seeing them in your output.
The for in loop iterates over keys, not values. So it's giving your the array indexes 0, 1, 2 not the values.
You could do it like this but it's bad practice to use a for in on an array.
for (var index in arr) {
indexes.push(arr[index]);
}
You should use a regular for loop
for (var i = 0; i < arr.length; i++) {
indexes.push(arr[i]);
}
for...in interates over the enumerable properties of an Object. The enumerable property of Array is the index.
More information can be found here.
AMCAScript 6 defines the for...of operator which allows iteration over the values. However this has not yet been adopted.
Yes, if you really want to use for in and not use the keys you can make the values into keys like this e.g.:
var arr = {'a':1,'b':1,'c':1};
for(var index in arr)
indexes.push(index);
same as setting arr['a']=1 etc. It's true that for..in iterates over the keys - not the values.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Loop through Json object
{
"data": [
{
"name": "Jen",
"id": "1"
},
{
"name": "Steve",
"id": "8"
}
]
}
A server I'm interacting with responds with the above.
I'm trying to loop through itenter code here for the For..in statement.
This is what I'm trying to do:
for (var item in response.data) {
console.log(item.name);
}
This doesn't work.
What went wrong?
Thank you
I GOT IT to work with the following after reading the comment:
for (var item in response.data) {
console.log(response.data[item].name);
}
I was able to get a list of names...
Can someone dissect the response as to why it worked?
data is actually an array (denoted by []), rather than an object so you want a regular for loop rather than a for in.
for (var i = 0; i<response.data.length; i++) {
// use i as an array index
console.log(response.data[i].name);
}
In JavaScript, the for in construct is used for iterating over object properties, but to iterate an array an incremental for loop is typically used.
Check out: Why is using "for...in" with array iteration a bad idea?
For...in iterates through names of the properties of an object. Array items are also considered "properties", so for..in iterates through indexes (which are 0, 1 in your case). As expected when you use response.data[0] you get first element of your array.
for..in iterates over the enumerable properties of an object in no particular order (you may get a different order in different browsers). An array is just a plain object with a special length method and handy methods inherited from Array.prototype (some of which depend on the special length property). There is no restriction on what can be used for a property name, they are not restricted to non-negative integers (noting that where a properly name is not a valid identifier, square bracket notation must be used to access its value).
The indexes of an array are just string property names (i.e. they are just plain object property names) that are non-negative integers, so a for..in loop will iterate over the numeric indexes (again, not necessarily in ascending or descending order) as well as all other enumerable properties, including those on the [[Prototype]] chain. Therefore it is always recommended to include a hasOwnProperty test with for..in unless you want to include inherited enumerable properties.
Because of the above, it is generally much better to iterate over array properties using a counter from 0 to array.length - 1 (since the length is always one bigger than the last index).
To test the "no particular order" statement, try the following in IE and other browser and note the different order:
var a = [];
a[2] = 2;
a[0] = 0;
a[3] = 3;
var b = [];
for (var i in a) b.push(a[i]);
alert(b);
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?
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)?
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++)
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.
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:
The properties are not necessarily returned in order (i.e. not 0, 1, 2 etc.)
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.
This question already has answers here:
What is the difference between for..in and for each..in in javascript?
(4 answers)
Closed 8 years ago.
I know in C# you use foreach like this: foreach string str in array1 {console.writeline(str);}
Is "for each ... in" used like that in JavaScript too?
Afaik only Firefox supportes for each...in. It is not part of any standard and most tools like JSLint will throw errors if they encountered it.
The difference is that for...in loops over the keys of an object whereas for each...in loops over the values.
So the recommended way is to not use for each and do
for (var key in obj) {
console.log(obj[key]);
}
instead.
Update: I cannot say how it relates to C#. But regarding arrays: Never use for...in to traverse arrays (yellow box here):
Although it may be tempting to use this as a way to iterate over an Array, this is a bad idea. The for...in statement iterates over user-defined properties in addition to the array elements, so if you modify the array's non-integer or non-positive properties (e.g. by adding a "foo" property to it or even by adding a method or property to Array.prototype), the for...in statement will return the name of your user-defined properties in addition to the numeric indexes.
Use a normal for loop instead:
for(var i = 0, l = arr.length; i<l; i++)
or more fancy:
for(var i = arr.length; i--;)
There is no for each in in standard JavaScript. It may exist in specific implementations, if they want to extend the language.
for..in in JavaScript only relates to arrays by association, because it relates to objects, and arrays are objects. for..in does not loop through array entries, as for each does in C#. Nor does it loop through array indexes although people tend to think it does. (It loops through property names; array indexes are property names, but an array object can have other properties as well.) It's more like for each with the keys of a dictionary. I've discussed this fairly thoroughly in this article.
"for each ... in" returns the values rather than the keys... See here:
http://www.dustindiaz.com/for-each-in/
The in operator is used to enumerate the properties (the names, not the values) of a javascript object - and in javascript, all non-primitives are objects (inherit from Object).
You use it like this
var obj = {
a: "aaa",
b: "bbb"
};
for (var key in obj) {
if (obj.hasOwnProperty(key)){
console.log("obj has a property " + key + ", with a value of " + obj[key]);
}
}
Since in also enumerates properties inherited through the prototype chain, we must use hasOwnProperty to check if these are indeed the objects own properties, and not just inherited ones.
Note that the in operator should never be used to enumerate the items stored in arrays - for this you should use a regular for/while loop using the index.
So basically I understand you can loop through an array in either of these ways.
var testarray = new Array(1,2,3,4);
for(i in testarray)console.log(testarray[i]);
//outputs 1,2,3,4
for(var i=0;i<testarray.length;i++) console.log(testarray[i]);
//outputs 1,2,3,4
My question how can I duplicate/emulate that array. With support for both of the for loop methods? Because when I do the same thing but I create my own function it includes length in the 1st for loop.
function emulatearray(){
for(var i = 0;i<arguements.length;i++)this[i]=arguments[i];
this.length = i;
}
var testarray = new emulatearray(1,2,3,4);
for(i in testarray)console.log(testarray[i]);
//outputs 1,2,3,4,null
for(var i=0;i<testarray.length;i++) console.log(testarray[i]);
//outputs 1,2,3,4
The for...in statement shouldn't be used to iterate over an array.
Quoting the Mozilla Dev Center:
for...in Statement
Although it may be tempting to use this as a way to iterate over an Array, this is a bad idea. The for...in statement iterates over user-defined properties in addition to the array elements, so if you modify the array's non-integer or non-positive properties (e.g. by adding a "foo" property to it or even by adding a method or property to Array.prototype), the for...in statement will return the name of your user-defined properties in addition to the numeric indexes.
Also, because order of iteration is arbitrary, iterating over an array may not visit elements in numeric order. Thus it is better to use a traditional for loop with a numeric index when iterating over arrays.
This is exactly the reason why you shouldn't use the for (i in array) ... construct. The JavaScript array's length property is internally declared as non-enumerable, so it doesn't appear when you iterate through the object, but any properties that you define are always enumerated.
The upcoming ECMAScript 5 has a way to define your own properties as non-enumerable, but most browsers don't support it as yet.