JavaScript中如何更优地克隆通过new创建的对象?
嘿,我完全理解你那种“这方法能用但总觉得不够优雅”的感受——克隆new出来的对象确实有更规范、更灵活的方案,分不同场景给你梳理下:
克隆通过
new创建的对象的更好方法 首先得明确:克隆分浅克隆和深克隆,不同需求对应不同方案,先从最常用的场景说起:
1. 浅克隆(适合无嵌套引用类型的对象)
如果你的对象只有字符串、数字、布尔这类基本类型属性,这两种方法简洁又高效:
扩展运算符(ES6+首选)
直接展开原对象的所有可枚举属性到新对象,写法超清爽:
const original = new YourCustomClass(); const clone = { ...original };
⚠️ 注意:这种方式会生成一个普通Object实例,而非原类的实例。如果不需要保留原类的方法/原型链,这完全够用。
Object.assign()
和扩展运算符效果一致,兼容性稍好(适合老项目):
const original = new YourCustomClass(); const clone = Object.assign({}, original);
2. 保留原类实例的克隆(需要继承原类方法)
如果克隆后的对象必须是原构造函数的实例(比如要调用原类的原型方法),可以这样做:
构造函数 + Object.assign
先创建一个原类的空实例,再把原对象的属性拷贝进去,既保留实例身份又完成克隆:
const original = new YourCustomClass(); const clone = new YourCustomClass(); Object.assign(clone, original);
如果原类的构造函数需要参数,你可以传入原对象的对应参数,或者先创建空实例再覆盖属性。
原型继承 + 属性拷贝
如果原类的构造函数有复杂初始化逻辑,不想重复执行,可以用Object.create继承原型,再拷贝属性:
const original = new YourCustomClass(); // 继承原对象的原型链 const clone = Object.create(Object.getPrototypeOf(original)); // 拷贝所有可枚举属性 Object.assign(clone, original);
3. 深克隆(处理嵌套引用类型)
如果对象里有嵌套的对象、数组这类引用类型,浅克隆只会拷贝引用(修改克隆对象的嵌套属性会影响原对象),这时候需要深克隆:
原生structuredClone(现代环境首选)
浏览器和Node.js都支持的原生API,能处理大部分类型(包括Date、RegExp、Map、Set等),用法简单:
const original = new YourCustomClass({ nested: { name: "test" } }); const clone = structuredClone(original);
⚠️ 限制:无法克隆函数、Symbol、DOM节点这类不可序列化的对象,遇到这些会报错。
手动递归克隆(自定义场景)
如果需要处理不可序列化的属性,或者要自定义克隆规则(比如跳过某些属性),可以写一个递归函数:
function deepClone(obj) { // 基本类型直接返回 if (obj === null || typeof obj !== 'object') return obj; // 处理数组 if (obj instanceof Array) { return obj.map(item => deepClone(item)); } // 处理自定义类实例 if (obj.constructor !== Object) { const cloneInstance = new obj.constructor(); // 拷贝自身属性 Object.assign(cloneInstance, obj); // 递归克隆嵌套属性 for (const key in obj) { if (obj.hasOwnProperty(key)) { cloneInstance[key] = deepClone(obj[key]); } } return cloneInstance; } // 处理普通对象 const plainClone = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { plainClone[key] = deepClone(obj[key]); } } return plainClone; } // 使用示例 const original = new YourCustomClass({ nested: { age: 20 } }); const clone = deepClone(original);
总结一下
- 浅克隆+不需要原类实例:用扩展运算符或
Object.assign - 浅克隆+需要原类实例:构造函数+
Object.assign或Object.create方案 - 深克隆:优先用
structuredClone,有特殊需求则手动递归
内容的提问来源于stack exchange,提问作者andrey
相关产品推荐
相关产品推荐

