I have a sample code taken from
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration#for...in_statement
(and just a little bit modified)
I don't understand why the for..of loop doesn't log 3, 'myStr', 5, 7, 'hello'
(doesn't log 'hello'
),
while the for..in loop DOES log all enumerables of arr 0, 1, 2, 3, foo
const arr = [3, 'myStr', 5, 7];
arr.foo = 'hello';
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "3", "foo"
}
console.log("------");
for (let i of arr) {
console.log(i); // logs 3, 'myStr', 5, 7
}
console.log("------");
console.log(arr); // logs [ 3, 'myStr', 5, 7, foo: 'hello' ]
console.log("------");
Any help appreciated!
( EDIT: When you press ">Run code snippet" (stackoverflow) it doesn't log the same as node.js (google V8 engine )
Node.js installed in my computer logs:
[
3,
"myStr",
5,
7,
foo: "hello"
]
">Run code snippet" (from stackoverflow) logs:
[
3,
"myStr",
5,
7
]
So maybe some answers aren't right/precise.
CodePudding user response:
The for ... of
loop is a method that maps over each item in the Array and stores the value of that element in a variable (in this case, i
).
The for ... in
loop is a method to map over each item in the Array and stores the key in the variable i
(which in this case is the index of the element).
It helps to understand that an Array is simply an Object with numerical keys / properties, so while the Array seems to be this:
[3, "myStr", 5, 7]
It is, in fact, this:
{
0: 3,
1: "myStr",
2: 5,
3: 7
}
CodePudding user response:
Unfortunately, I don't think your "foo" property is technically considered "iterable" in the context of the JavaScript Array you've assigned it to.
Each type of iterable object, including built-ins like Array, can define their own method of determining which values come next in an iteration. So the mechanism that moves from one value to the next during for...of
isn't strictly bound to the properties assigned to the object, the way that for...in
is.
With that said, if you're really interested in fiddling around with JavaScript's iteration protocol,this functionality does afford you the ability to build your own iterables that express the iteration behavior you're hoping to achieve here. If you're simply hoping to access a list of values associated with Object property names, the the old-fashioned for...in
loop in which you access each value by property name is probably the easiest approach.
EDIT: I see your edit above about the difference between the logging output of the code snippet and your node console. I'd urge you not to get too hung up on this discrepancy, as the implementation-specific behavior of console.log
may not fully reflect the structures they're logging. The following snippet expands on your initial experiment to illustrate the difference between "iterable array structure" and "non-iterable object structure":
const arr = [3, 'myStr', 5, 7];
arr.foo = 'hello';
// Here's the array structure,
// note that it lacks the "foo" property assigned to the "arr" object.
console.log('Array structure: ', arr);
// Here's the ".length" property of arr,
// which shows the number of iterable items in its array structure.
console.log('Array length property: ', arr.length);
// Here is the list of in the arr object,
// Including the array indices, and "foo".
console.log('Object keys in "arr" object: ', Object.keys(arr));
// Here's the '.length' property of arr's object key list.
console.log('Number of keys in "arr" object: ', Object.keys(arr).length);