Reputation: 154
Consider the following code.
const iterable = [10, 20, 30];
for (let value of iterable) {
value += 1;
console.log(value);
}
// 11
// 21
// 31
console.log(('after for...of'), iterable); // [10, 20, 30] - no change
const iterable1 = [10, 20, 30];
for (let i = 0; i < iterable1.length; i++) {
iterable1[i] += 1;
console.log(iterable1[i]);
}
// 11
// 21
// 31
console.log(('after regular for...'), iterable1); // [11, 21, 31] - values changed
As you see and as was stated in the question, the values in the array didn't change after the for...of
loop, but did after the regular for
loop.
After reading this article on MDN about the for... of
I was led to believe that(at least in this particular context) it would be identical to the for
loop, but as you see, this has proven not to be the case. It is especially baffling for me since the article states that
It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object.
The article proceeds to state that you can reassign values of the iterable(in our case, an array) inside the block.
You can use
let
instead ofconst
too, if you reassign the variable inside the block.
It would seem to me that I lack some critical (maybe even trivial) insight into how the for...of
works, and I hope you could help me better understand what is going on.
Upvotes: 0
Views: 2560
Reputation: 2300
Might be helpful to look at a for...of
loop as similar to a function.
Remember, in a function when you pass in an argument that is a primitive data-type, the parameter for that argument will receive a 'copy' of that argument's primitive value. Any changes made to the parameter will not effect the outside variable|argument.
And, when you pass in an argument that is an object, the parameter for that argument gets a copy of the address in memory of the object e.g. it will refer to the same object. Any changes made to the parameter will effect the outside variable|argument.
The code snippet below demonstrates these two ideas:
primitiveVariable = 1;
obj = {num: 1};
function f(primitive, object) {
primitive+=1;
object.num+=1;
console.log(primitive);
console.log(object)
}
f(primitiveVariable, obj);
console.log(primitiveVariable);
console.log(obj);
A for...of
loop operates the same:
a = [1, 2, 3];
for (item of a) {
item += 1;
}
console.log(a);
for (item of a) {
a[0] = item;
}
console.log(a);
Upvotes: 2
Reputation: 50291
In the first case you are just accessing the value but after after increment you are not setting it back to the array. Since array index is not available while using for...of
you can use entries
const iterable = [10, 20, 30];
for (const [i, v] of iterable.entries()) {
iterable[i] = v + 1
}
console.log(('after for...of'), iterable);
Upvotes: 2
Reputation: 413737
In your for ... of
loop, on each iteration value
is a copy of an element in the array. Thus,
value += 1;
is critically different from
iterable1[i] += 1;
The value += 1;
statement does work, and after that value
will indeed contain a number one greater than an element of the array. However, the element of the array itself remains unchanged.
Consider this simpler case:
let x = 0, y;
y = x;
y += 1;
console.log(x);
you would see no change to the value of x
. The variable y
is also just a copy of the value of x
, so when y
changes, x
is unaffected.
Upvotes: 4