Object.create本身不实现浅拷贝,它创建以指定对象为原型的新空对象;结合Object.assign可派生出继承原型且拥有独立自有属性的新实例,但引用类型仍共享。

使用 Object.create 本身**不直接实现浅拷贝**,它创建的是以指定对象为原型的新空对象;但可以结合 Object.assign 或手动遍历自有属性,基于字面量(plain object)派生出继承其原型、同时拥有独立属性的新实例——这正是“基于既有字面量派生新实例”的典型做法。
理解 Object.create 的核心作用
Object.create(proto, [propertiesObject]) 创建一个新对象,其内部 [[Prototype]] 指向 proto。它不会复制 proto 的属性到新对象上,新对象初始是空的(除非通过 propertiesObject 显式定义自身属性)。
例如:
const base = { a: 1, b: 2 };
const derived = Object.create(base);
console.log(derived.a); // 1 ← 从原型链读取
console.log(derived.hasOwnProperty('a')); // false ← 自身无 a
用 Object.create + Object.assign 实现“带自有属性的派生实例”
若希望新实例**继承原字面量的原型行为**(比如方法),又**拥有自己的一份数据属性副本**(即浅拷贝效果),推荐组合使用:
- 用
Object.create(base)设定原型 - 用
Object.assign(newObj, base)将base的可枚举自有属性复制到新对象自身
const base = {
name: 'default',
tags: ['a', 'b'],
greet() { return `Hello, ${this.name}`; }
};
const instance = Object.assign(Object.create(base), base);
// instance 现在:
// → [[Prototype]] 是 base(可调用 greet)
// → 自身拥有 name 和 tags 的副本(修改不影响 base)
instance.name = 'custom'; // ✅ 修改自身属性
instance.tags.push('c'); // ⚠️ 仍共享引用(浅拷贝限制)
console.log(base.name); // 'default' ← 未变
console.log(base.tags); // ['a', 'b', 'c'] ← 被意外修改!
注意浅拷贝的局限性:引用类型仍共享
上述方式是**浅拷贝**:只复制第一层属性值。对对象、数组等引用类型,复制的是引用地址,不是新副本。因此:
- 修改
instance.tags数组内容会影响base.tags - 若需完全隔离,应对引用属性单独深拷贝(如用
structuredClone、LodashcloneDeep,或手动处理) - 若只需“派生+隔离原始数据”,更安全的做法是仅继承方法,数据属性由构造逻辑初始化
更健壮的派生模式:分离行为与状态
推荐将可复用的方法定义在原型(如 base 对象),而数据属性由实例自行持有:
const BaseBehavior = {
greet() { return `Hello, ${this.name}`; },
addTag(tag) { this.tags.push(tag); }
};
// 派生实例:继承行为,但数据独立初始化
const instance = Object.assign(Object.create(BaseBehavior), {
name: 'Alice',
tags: ['x', 'y'] // ✅ 新数组,与他人无关
});
instance.addTag('z'); // 安全:只改自己的 tags
这种方式清晰分离了“共享行为”和“独有状态”,避免浅拷贝副作用,也更符合面向对象的设计直觉。


















