JavaScript如何按值而非引用将对象push进数组?循环场景解决方案
问题原因
JavaScript中对象属于引用类型,你每次arr.push(foo)存入数组的是foo对象的内存引用,而非独立的对象副本。后续对foo.a的修改会作用于所有指向同一块内存地址的引用,所以最终数组内所有元素都显示为最后修改的值。
解决方案
方案1:每次存入数组时创建对象副本(适用需要复用原对象的场景)
单层对象用浅拷贝即可
使用扩展运算符或者Object.assign生成新对象:
let foo = {"a": 1}; let arr = []; for (let i=0;i<10;i++) { // 扩展运算符浅拷贝生成新对象 arr.push({...foo}); // 也可替换为 arr.push(Object.assign({}, foo)); foo.a += 1; }
多层嵌套对象用深拷贝
如果对象存在多层嵌套,浅拷贝只会复制顶层结构,嵌套层级还是引用关系,此时用structuredClone做结构化深拷贝:
arr.push(structuredClone(foo));
注意:
JSON.parse(JSON.stringify(foo))也可实现深拷贝,但无法处理函数、循环引用、Symbol、BigInt等特殊类型,优先用structuredClone。
方案2:循环内直接生成新对象(无原对象修改需求的最优方案)
不需要提前声明复用foo对象的话,直接在循环内创建对应值的新对象,省去拷贝开销:
let arr = []; for (let i=0;i<10;i++) { arr.push({a: i+1}); }
两种方案运行后arr的输出都符合你的预期。
内容的提问来源于stack exchange,提问作者The Bic Pen
相关产品推荐
相关产品推荐

