JavaScript forEach处理对象时引用赋值导致结果异常问题
问题根源
你对问题的判断是准确的,核心问题出在两个JavaScript引用类型的使用误区上:
- 直接赋值
let prodVariation = product不会复制对象,只是创建了一个指向原对象的引用,后续所有对prodVariation的修改都会直接改动原product对象。你第一次推入newData的原始商品、后续循环推入的变体,本质全是指向同一个内存对象的引用,所以最终所有数组项都会显示最后一次修改后的结果。 - 循环拼接编码时,你是在
prodVariation.Code的当前值基础上追加内容,就算提前做了一次对象复制,如果把复制操作放在尺寸循环外面,还是会出现编码累加的问题。
修复代码
直接替换原有逻辑即可,运行后就能得到你预期的结果:
let data = [{ "Code": "COD01", "Size Options": "85-90-95-100", }, { "Code": "COD02", "Size Options": "85-90-95-100", }]; let newData = []; data.forEach(function(product) { // 推入原始商品时做浅拷贝,避免后续修改影响这一项 newData.push({...product}); if (product["Size Options"].includes('-')) { const variations = product["Size Options"].split('-'); // 缓存原始编码,所有变体都基于原始编码拼接,避免累加 const baseCode = product["Code"]; variations.forEach(function(size) { // 每次生成都创建全新的对象副本,不复用引用 const variant = {...product}; variant["Code"] = `${baseCode}-${size}`; newData.push(variant); }); } }); console.log('New data:'); console.log(JSON.stringify(newData, null, 4));
补充说明
- 如果需要兼容不支持ES6展开运算符的老旧环境,可以把
{...product}替换为Object.assign({}, product),浅拷贝效果完全一致。 - 由于你的商品对象所有属性都是字符串这类基础类型,浅拷贝完全可以满足需求,不需要额外做深拷贝处理。
内容的提问来源于stack exchange,提问作者Leonardo Dias
相关产品推荐
相关产品推荐

