JavaScript中forEach遍历数组时更新元素的行为解析
这问题我之前踩过坑,本质是JavaScript的参数传递规则和forEach()的工作机制在起作用,我给你拆解清楚:
1. forEach回调里的employee是什么?
当你调用employees.forEach((employee) => { ... })时,回调函数里的employee其实是数组对应元素的引用副本——注意,是“引用的副本”,不是元素本身。
举个例子,数组里的第二个元素是{ name: { first: 'A', last: 'B' }, age: 54 },回调里的employee变量只是存了指向这个对象的引用。当你写employee = youngerEmployee时,你只是把这个局部的employee变量的指向改成了新的youngerEmployee对象,但原数组里的那个位置的引用根本没被改变。就像你拿了一把钥匙(引用)去开房间(对象),然后你把钥匙换成了另一把,原来的房间还是原来的,数组里存的还是原来那把钥匙。
2. 通过索引修改为什么能生效?
如果你在forEach回调里记录下当前元素的索引index,之后执行employees[index] = youngerEmployee,这是直接操作数组的存储空间——你把数组第index个位置的引用直接替换成了youngerEmployee的引用,相当于把数组里原来的钥匙换成了新钥匙,数组自然就更新了。
额外补充:如果是修改对象属性为啥能行?
要是你在forEach里写employee.age = 25,这时候是能生效的。因为这时候你没有替换employee变量的指向,而是通过它的引用去修改了对象本身的属性,原数组里的对象还是那个对象,只是内部属性变了,所以数组会同步变化。但你现在的需求是替换整个对象,所以必须直接操作数组的索引位置。
再用你的代码验证一下
失败的代码逻辑:
employees.forEach( (employee) => { if (employee.age > 50) { employee = youngerEmployee; // 只是改了局部变量employee的指向,原数组没变化 } });
可行的逻辑(比如先存索引再修改):
let targetIndex = -1; employees.forEach( (employee, index) => { if (employee.age > 50) { targetIndex = index; // 记录要修改的数组位置 } }); if (targetIndex !== -1) { employees[targetIndex] = youngerEmployee; // 直接修改数组的对应位置,生效 }
或者更直接的,在forEach里直接用索引修改也行:
employees.forEach( (employee, index) => { if (employee.age > 50) { employees[index] = youngerEmployee; // 直接操作数组索引,生效 } });
内容的提问来源于stack exchange,提问作者Karma

