在 JavaScript 中,深拷貝(Deep Copy)是一種創建對象完整副本的方式,其中所有的嵌套對象或數組也會被拷貝,而不是共享原始對象的引用。以下是一些常見的深拷貝方法:
使用 JSON.stringify() 和 JSON.parse() 將對象轉換為 JSON 字符串後再解析為新對象。
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
console.log(deepCopy); // { a: 1, b: { c: 2 } }
console.log(deepCopy.b === obj.b); // false
簡單易用,適合純 JSON 結構(不含函數、undefined、Symbol 等)。
不能處理循環引用(如 obj.a = obj)。
丟失特殊數據類型(如 Date、Set、Map 等)。
手動實現遞歸拷貝,適合處理更複雜的數據結構。
function deepCopy(obj) {
if (obj === null || typeof obj !== "object") return obj;
// 處理數組
if (Array.isArray(obj)) {
return obj.map(item => deepCopy(item));
}
// 處理對象
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopyObj = deepCopy(obj);
console.log(deepCopyObj); // { a: 1, b: { c: 2 }, d: [3, 4] }
console.log(deepCopyObj.b === obj.b); // false
Lodash 的 cloneDeep
Lodash 提供了一個高效且功能強大的深拷貝方法。
const _ = require("lodash");
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopy = _.cloneDeep(obj);
console.log(deepCopy); // { a: 1, b: { c: 2 }, d: [3, 4] }
console.log(deepCopy.b === obj.b); // false
structuredClone 是一個現代瀏覽器支持的內置方法,用於深拷貝。
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopy = structuredClone(obj);
console.log(deepCopy); // { a: 1, b: { c: 2 }, d: [3, 4] }
console.log(deepCopy.b === obj.b); // false
結合 Object.assign 或展開運算符,實現手動深拷貝。
function deepCopy(obj) {
if (obj === null || typeof obj !== "object") return obj;
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopyObj = deepCopy(obj);
console.log(deepCopyObj); // { a: 1, b: { c: 2 }, d: [3, 4] }
console.log(deepCopyObj.b === obj.b); // false
針對特定場景(如 Date、Map、Set),手動處理深拷貝。
function deepCopy(obj) {
if (obj === null || typeof obj !== "object") return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof Map) return new Map([...obj]);
if (obj instanceof Set) return new Set([...obj]);
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const obj = { a: new Date(), b: new Map([[1, "one"]]), c: new Set([2, 3]) };
const deepCopyObj = deepCopy(obj);
console.log(deepCopyObj); // 深拷貝的對象,保持特殊類型