为何两段相似JavaScript代码输出结果不一致?求解析
问题:两段相似JavaScript代码输出不同的原因
期望两段逻辑相似的JavaScript代码得到相同输出,即processedData2最终输出为:
[ { "id": "someid", "parts": [ { "part_id": "1" } ] }, { "id": "someid", "parts": [ { "part_id": "2" } ] }, { "id": "someid", "parts": [ { "part_id": "3" } ] } ]
但示例1未达预期,示例2运行正常,两段代码看似一致,求原因。
示例1(未达预期)
let putData = [ { id: 'someid', parts: [ { part_id: '1', }, { part_id: '2', }, { part_id: '3', }, ], }, ]; let processedData = []; for (let i of putData) { for (let o in i.parts) { processedData.push(i); } } console.log('processed Data ', processedData); let processedData2 = processedData; console.log('processedData 2 before ', processedData2); for (let i = 0; i < processedData.length; i++) { console.log(processedData[i].parts[i]); processedData2[i].parts = [processedData[i].parts[i]]; console.log(processedData2[i].parts[i]); } console.log('processedData 2 after', processedData2);
示例2(运行正常)
let processedData = [ { id: 'someid', parts: [ { part_id: '1', }, { part_id: '2', }, { part_id: '3', }, ], }, { id: 'someid', parts: [ { part_id: '1', }, { part_id: '2', }, { part_id: '3', }, ], }, { id: 'someid', parts: [ { part_id: '1', }, { part_id: '2', }, { part_id: '3', }, ], }, ]; console.log('processed Data ', processedData); let processedData2 = processedData; console.log('processedData 2 before ', processedData2); for (let i = 0; i < processedData.length; i++) { console.log(processedData[i].parts[i]); processedData2[i].parts = [processedData[i].parts[i]]; console.log(processedData2[i].parts[i]); } console.log('processedData 2 after', processedData2);
核心原因:引用类型的指向差异
- 示例1中,
processedData数组的3个元素都是同一个对象的引用:循环for (let i of putData) { for (let o in i.parts) { processedData.push(i); } }只是把putData[0]这个对象的引用重复push了3次,数组里的三个元素本质指向内存中同一个对象。 - 后续修改
processedData2[i].parts时,实际是在修改同一个对象的parts属性:第一次循环(i=0)把该对象的parts改成[{part_id: '1'}],第二次循环(i=1)时,processedData[1].parts已经变成了只有1个元素的数组,访问processedData[1].parts[1]会得到undefined,最终导致所有元素的parts都被改成异常值。 - 示例2中,
processedData数组的3个元素是三个独立的对象(结构相同但内存地址不同),修改其中一个对象的parts属性不会影响另外两个,因此能得到预期结果。
示例1的修复方案
每次push时创建原对象的浅拷贝(此处浅拷贝足够),确保数组元素是独立对象:
// 替换原push逻辑 processedData.push({...i, parts: [...i.parts]});
内容的提问来源于stack exchange,提问作者Tobi
相关产品推荐
相关产品推荐

