如何在JavaScript中深度克隆数组并保留类型且避免引用关联?
解决JavaScript数组深度克隆并保留Date类型的问题
针对你包含Date对象和嵌套对象的数组const a = [1, new Date(), false, { date: new Date(), name: "John Doe" }],以下是两种可行的克隆方案:
方案一:使用原生structuredClone API
这是ES2022引入的原生深度克隆API,专门解决复杂类型的深拷贝问题,能直接保留Date、Map、Set等内置类型,且无需手动编写递归逻辑:
const a = [1, new Date(), false, { date: new Date(), name: "John Doe" }]; const clonedA = structuredClone(a); // 验证克隆效果 clonedA[3].name = "Jane Doe"; clonedA[3].date.setFullYear(2025); clonedA[1].setFullYear(2026); console.log(a[3].name); // 输出 "John Doe"(原数组不受影响) console.log(a[3].date.getFullYear()); // 输出原日期年份(不受修改影响) console.log(a[1].getFullYear()); // 输出原日期年份(不受修改影响)
注意:structuredClone不支持克隆函数、Symbol值、循环引用对象(如果需要处理循环引用,可以在自定义函数中添加缓存),但对于你的场景完全适用。
方案二:自定义递归深度克隆函数
如果需要兼容不支持structuredClone的旧环境(如IE),或者需要自定义克隆逻辑,可以手动实现递归克隆:
function deepClone(obj) { // 处理基本类型、null和undefined if (obj === null || typeof obj !== 'object') return obj; // 单独处理Date类型 if (obj instanceof Date) { return new Date(obj.getTime()); } // 处理数组 if (Array.isArray(obj)) { return obj.map(item => deepClone(item)); } // 处理普通对象 const clonedObj = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { clonedObj[key] = deepClone(obj[key]); } } return clonedObj; } // 使用示例 const a = [1, new Date(), false, { date: new Date(), name: "John Doe" }]; const clonedA = deepClone(a); // 验证修改不影响原数组 clonedA[3].name = "Jane Doe"; console.log(a[3].name); // 输出 "John Doe"
如果需要处理循环引用,可以给函数添加一个缓存参数(如new WeakMap()),记录已克隆的对象,避免递归栈溢出。
总结
- 现代环境优先使用
structuredClone,简洁高效且原生支持类型保留; - 旧环境或需要自定义逻辑时,使用递归深度克隆函数。
内容的提问来源于stack exchange,提问作者Simon Trichereau
相关产品推荐
相关产品推荐

