Object.create(Object.getPrototypeOf(obj))仅创建继承原对象原型的空对象,不复制任何属性,因此不是深克隆。真正保留原型的深克隆需先递归拷贝所有属性(含symbol、getter/setter等),再设置新对象原型为原对象原型。
Object.create(Object.getPrototypeOf(obj)) 本身只能创建一个**新对象并继承原对象的原型链**,它不复制属性,更不是深克隆。把它当作“深克隆方法”是一种常见误解。
这行代码只完成两件事:
结果是:新对象和原对象共享同一原型链,但所有数据属性(如 {a: 1, b: {c: 2}} 中的 a 和 b)都完全没被复制——新对象是空的。
深克隆要求:
Object.create(...) 连最基础的属性复制都没做,自然不满足任何一条。
需要分两步:先深拷贝属性值,再把结果对象的原型设为原对象的原型。推荐组合使用:
Object.getOwnPropertyDescriptors(obj) 获取所有属性描述符(含 getter/setter、writable、enumerable、configurable),再用 Object.defineProperties(新对象, descriptors)
Object.setPrototypeOf(新对象, Object.getPrototypeOf(obj)) 或在 Object.create 创建时传入(但注意:create 只设 [[Prototype]],不设属性)简单示意(无循环引用处理):
function cloneWithPrototype(obj) { if (obj === null || typeof obj !== 'object') return obj; // 创建空对象,原型设为 obj 的原型 const cloned = Object.create(Object.getPrototypeOf(obj)); // 获取所有自有属性描述符 const descriptors = Object.getOwnPropertyDescriptors(obj); // 逐个克隆属性值并定义到新对象 for (const key in descriptors) { const desc = descriptors[key]; if ('value' in desc) { desc.value = cloneWithPrototype(desc.value); // 递归克隆值 } Object.defineProperty(cloned, key, desc); } return cloned;}
lodash.cloneDeep,它默认保留原型(v4.17+),且健壮处理各种边界Object.create 入手想“一步到位”,而应明确分离“原型继承”和“属性深拷贝”两个职责