You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两个JavaScript对象共用同一数组?原因与解决方法

嘿,这个问题我太熟了!让我一步步给你拆解清楚:

问题原因

你遇到的核心问题是原型链上的引用类型会被所有实例共享,而基本类型看起来正常是因为赋值逻辑不同:

  • 首先,Object.create(OBJ)创建的新对象,会把OBJ作为它的原型对象(也就是内部的[[Prototype]])。当你访问实例的属性时,会先找自己的属性,如果没有才会顺着原型链往上找。
  • 对于像id这种基本类型:当你执行obj1.id = 1时,其实是在obj1自身添加了一个id属性,直接覆盖了原型上的id。后续访问obj1.id会优先取自己的,obj2同理,所以看起来各自独立。
  • 但对于arr这种引用类型(数组是引用类型):当你执行obj1.arr.push(1)时,你并没有给obj1添加自己的arr属性,而是直接修改了原型链上OBJ的arr数组——因为你只是在操作数组的内容,而不是给obj1赋值新的数组。所以obj2访问arr时,还是会去原型上找,自然看到的是被修改后的同一个数组。
正确实现方式

这里给你几种常用的解决办法,按需选择:

方法1:使用构造函数

构造函数会在每次实例化时,给新对象创建独立的属性,包括引用类型:

function MyObj() {
  this.id = 0;
  this.arr = [0, 0]; // 每个实例都会得到自己的数组
}

let obj1 = new MyObj();
let obj2 = new MyObj();

// 现在操作各自的arr就不会互相影响了
obj1.arr.push(1);
console.log(obj1.arr); // [0,0,1]
console.log(obj2.arr); // [0,0]

方法2:Object.create后手动添加实例自身的引用类型

如果还是想用Object.create,可以在创建实例后,给每个实例赋值自己的数组:

// 原型上可以保留共享属性,或者去掉引用类型
var OBJ = { id: 0 };

let obj1 = Object.create(OBJ);
obj1.arr = [0, 0]; // 给obj1创建自己的arr

let obj2 = Object.create(OBJ);
obj2.arr = [0, 0]; // 给obj2创建自己的arr

如果原型上需要保留默认的数组值,也可以浅拷贝原型的数组来创建新的:

var OBJ = { id: 0, arr: [0,0] };

let obj1 = Object.create(OBJ);
obj1.arr = [...OBJ.arr]; // 浅拷贝原型数组,生成新数组
// 也可以用 obj1.arr = OBJ.arr.slice();

let obj2 = Object.create(OBJ);
obj2.arr = [...OBJ.arr];

方法3:ES6类(语法糖,本质和构造函数一致)

如果喜欢更现代的语法,可以用ES6的类:

class MyObj {
  constructor() {
    this.id = 0;
    this.arr = [0, 0];
  }
}

let obj1 = new MyObj();
let obj2 = new MyObj();

简单总结下:要让每个实例拥有独立的引用类型,关键是在实例初始化阶段给每个实例创建属于自己的引用类型实例,而不是依赖原型上的那个共享引用。

内容的提问来源于stack exchange,提问作者Geo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:58:52