为何数组objArr中反复出现同一对象,且推入的多对象值均相同?
为什么数组里反复出现同一个对象?
这种情况我在开发中碰到过好多次,核心原因其实是你每次推入数组的都是同一个对象的引用,而不是新创建的独立对象。
在JavaScript里,对象属于「引用类型」,和字符串、数字这类「值类型」不一样:
- 值类型赋值时,会直接复制一份具体的值;
- 引用类型赋值时,复制的是指向对象的内存地址,而不是对象本身。
举个错误代码的例子,你大概率是这么写的:
const objArr = []; // 只在循环外创建了一个对象 const tempObj = {}; for (let i = 0; i < 3; i++) { // 每次循环只是修改这个对象的属性 tempObj.id = i; tempObj.name = `Item ${i}`; // 推入数组的都是同一个tempObj的引用 objArr.push(tempObj); } console.log(objArr); // 输出结果:三个对象全是 {id: 2, name: "Item 2"}
为什么会这样?因为tempObj只被创建了一次,所有循环里的修改都是在同一个对象上操作,数组里的每一项都指向这个唯一的对象。当循环结束时,对象的属性是最后一次修改的值,所以数组里所有项看起来都一模一样。
解决方法
要解决这个问题,核心就是每次推入数组时,都创建一个新的对象实例,常见的两种方式:
1. 在循环内部创建新对象
把对象的创建逻辑放到循环里,确保每次迭代都生成一个全新的对象:
const objArr = []; for (let i = 0; i < 3; i++) { // 每次循环都新建一个对象 const tempObj = {}; tempObj.id = i; tempObj.name = `Item ${i}`; objArr.push(tempObj); } console.log(objArr); // 输出三个独立的对象:[{id:0,...}, {id:1,...}, {id:2,...}]
2. 基于模板对象创建新实例
如果你需要基于某个基础模板对象生成新对象,可以用扩展运算符...或者Object.assign()来实现浅复制,生成新对象:
const objArr = []; // 基础模板对象 const baseObj = { type: "default", status: "active" }; for (let i = 0; i < 3; i++) { // 复制模板属性,同时添加/覆盖新属性,生成新对象 const newObj = { ...baseObj, id: i, name: `Item ${i}` }; objArr.push(newObj); } console.log(objArr); // 每个对象都是独立实例,模板属性保留,id和name各自不同
注意:如果模板对象有嵌套的子对象,浅复制会导致子对象还是共享引用,这时候需要用深复制(比如
JSON.parse(JSON.stringify(baseObj))或者自定义递归深复制函数)。
总结
本质就是要区分「引用类型」和「值类型」的差异,确保数组里的每一项都是独立的对象实例,而不是指向同一个对象的引用。只要每次推入数组时都新建对象,就能解决这个问题啦。
内容的提问来源于stack exchange,提问作者Black
相关产品推荐
相关产品推荐

