object.create 用于创建原型继承对象而非浅拷贝;要实现浅拷贝需配合 object.getownpropertydescriptors 和 object.defineproperties,或更简洁地使用展开运算符 {...obj} 或 object.assign({}, obj)。

Object.create 可以创建一个新对象,并将其原型指向指定对象,但它本身不直接实现浅拷贝;要基于既有对象字面量快速派生新实例(即创建具有相同自有属性值、但独立可修改的新对象),需配合 Object.getOwnPropertyDescriptors 和 Object.defineProperties,或更简洁地用展开运算符或 Object.assign。单纯用 Object.create(obj) 得到的是原型继承关系,不是浅拷贝。
理解 Object.create 的真实作用
Object.create(proto, propertiesObject) 创建的对象,其 [[Prototype]] 指向 proto,所有属性默认是继承来的(除非显式定义在自身)。若传入一个普通对象字面量作为 proto,新对象并不拥有该对象的自有属性副本,只是能通过原型链访问——修改原对象属性会影响所有继承它的实例(如果属性是引用类型且未被遮蔽)。
- 它适合构建“类式”原型继承结构,而非数据拷贝
- 直接用于“派生实例”易导致意外交互,尤其当原对象含数组、对象等引用值时
- 若目标是隔离数据,必须将源对象的自有属性复制到新对象自身上
用 Object.create + getOwnPropertyDescriptors 实现真正浅拷贝
若坚持使用 Object.create 作为基础(例如需要保留特定原型链),可通过获取源对象所有自有属性描述符并重新定义到新对象上来达成浅拷贝效果:
- 先用
Object.create(Object.getPrototypeOf(obj))创建空对象,继承原对象的原型 - 再用
Object.getOwnPropertyDescriptors(obj)获取所有自有属性的键值和配置(如 writable、enumerable) - 最后用
Object.defineProperties(newObj, descriptors)将这些属性(含值)复制到新对象自身
这样得到的新对象与原对象拥有相同自有属性值,且互不影响(基本类型值天然隔离,引用类型值仍共享——这就是“浅”拷贝的本质)。
更推荐的快捷方式:展开运算符与 Object.assign
对大多数场景,“基于对象字面量快速派生新实例”无需绕路 Object.create。现代 JavaScript 提供更直观、安全的方式:
-
{...obj}:适用于 plain object,会复制所有可枚举自有属性(不含 symbol、不可枚举属性、原型方法) -
Object.assign({}, obj):行为类似展开运算符,也只处理可枚举自有属性,兼容性更好 - 两者都生成全新对象,自有属性值直接赋值,满足浅拷贝语义,代码简洁易读
若需保留不可枚举属性或 symbol 键,才需回到 getOwnPropertyDescriptors 方案。
注意浅拷贝的边界与常见陷阱
无论用哪种方法,浅拷贝只复制第一层属性值:
- 遇到字符串、数字、布尔值等基本类型,拷贝后完全独立
- 遇到对象、数组、函数等引用类型,拷贝的是引用地址,新旧对象仍共享同一底层数据
- 若需完全隔离(深拷贝),应使用
structuredClone(现代环境)、JSON.parse(JSON.stringify())(简单场景,有局限)或专用库
派生新实例时,务必确认是否真需要“浅”——有时业务逻辑要求深层独立,此时不应止步于浅拷贝。











