问题描述
请考虑以下代码。
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,30] - no change
const iterable1 = [10,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
正如您所看到的和在问题中所指出的那样,数组中的值在for...of
循环之后没有改变,但是在常规for
循环之后却没有改变。
在阅读关于for... of
的{{3}}之后,我被认为(至少在此特定上下文中)它与for
循环相同,但是正如您所看到的,事实证明并非如此。因为这篇文章指出,
本文继续指出,您可以在块内重新分配iterable(在我们的情况下为数组)的值。
如果在块内重新分配变量,也可以使用
let
代替const
。
在我看来,我对for...of
的工作方式缺乏关键的(甚至是微不足道的)见解,希望您能帮助我更好地了解正在发生的事情。
解决方法
在您的for ... of
循环中,每次迭代value
都是数组中元素的副本。因此,
value += 1;
与
有很大不同iterable1[i] += 1;
value += 1;
语句可以正常工作,并且之后value
的确比数组元素大一个数字。但是,数组本身的元素保持不变。
考虑以下简单情况:
let x = 0,y;
y = x;
y += 1;
console.log(x);
您不会看到x
的值有任何变化。变量y
也是x
值的副本,因此,当y
更改时,x
不受影响。
在第一种情况下,您只是访问该值,但在递增之后,您并没有将其设置回数组。由于使用for...of
时数组索引不可用,因此可以使用entries
const iterable = [10,20,30];
for (const [i,v] of iterable.entries()) {
iterable[i] = v + 1
}
console.log(('after for...of'),iterable);
,
将for...of
循环视为类似于函数可能会有所帮助。
请记住,在函数中传入原始数据类型的参数时,该参数的参数将收到该参数原始值的“副本”。对参数所做的任何更改都不会影响外部变量。
而且,当您传入作为对象的参数时,该参数的参数会获取对象内存中地址的副本,例如它将引用相同的对象。对参数所做的任何更改都会影响外部变量|
。下面的代码段演示了这两个想法:
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);
for...of
循环的运行方式相同:
a = [1,2,3];
for (item of a) {
item += 1;
}
console.log(a);
for (item of a) {
a[0] = item;
}
console.log(a);