- 使用JSON.parse(JSON.stringify(obj)):
const obj2 = JSON.parse(JSON.stringify(obj1));
這是最簡單的深拷貝方法,但所有非JSON支持的類型都將被忽略或轉換,日期會被轉換為字串,正規表達式會被丟棄。但是它的整體效能快,非常適合使用在小型且簡單的物件身上。
2. 使用lodash
的cloneDeep
身為前端開發中的老牌子,第三方資料處理的套件, lodash
可以說是耳熟能詳,它本身提供了許多方便的函式來幫我們處理跟資料有關的計算。
它提供了cloneDeep
函數,能夠更全面的深拷貝各種資料類型。
import _ from 'lodash';
const newObj = _.cloneDeep(obj1);
3. 透過遞迴的方式來撰寫深拷貝的函式
function deepCopy(obj, hash = new WeakMap()) {
if (obj === null) return null;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== 'object') return obj;
if (hash.has(obj)) return hash.get(obj);
const cloneObj = new obj.constructor();
hash.set(obj, cloneObj);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepCopy(obj[key], hash);
}
}
return cloneObj;
}
const obj1 = {
name: 'mike',
info: {
age: 12,
address: 'taiwan',
sex: 'boy',
interest: {
code: 'javascript',
sports: 'basketball',
watch: 'movie',
},
},
};
const obj2 = deepCopy(obj1);
obj2.info.interest.code = "php";
console.log(obj1.info.interest);
console.log(obj2.info.interest);
可以通過遞迴的方式來實現深拷貝,這給了我們在開發上面的靈活性,不過這種方式在開發的管理上面就顯得有點笨重。
接下來我要介紹第四種方法,也是重頭戲
4. 使用原生的 structuredClone 來進行深拷貝
structuredClone 是 2022 年出來的新的 API,專門處理深拷貝的。在以前,我們常用JSON.parse(JSON.stringify(obj))
來做深拷貝,但這個方法有很多問題。它不能複製函數、忽略undefined
,也不能處理循環參考。而structuredClone
就像是一個升級版,它能搞定這些情況,而且使用起來超級簡單。
const obj2 = structuredClone(obj1);
就這樣,二者完全獨立,互不影響,它真的很方便,尤其是在處理那些複雜的物件時。
但 structuredClone 也不是完美的,它也有一些限制
- 函數無法複製:就像大多數的深拷貝方法一樣,
structuredClone
不能複製函數。 - 某些物件型別不支持:雖然
structuredClone
支持許多內建的JavaScript type,但它並不支持複製某些特殊類型的物件,比如Error
、Function
等。 - 瀏覽器支援度:雖然現代瀏覽器大多支持
structuredClone
,但在一些舊版本的瀏覽器中可能不支援。如果你的網站支援較舊瀏覽器,可能需要考慮其他替代方案。 - 轉換特殊類型時的行為差異:對於一些特殊類型的對象,比如
Map
、Set
、ArrayBuffer
、DataView
等,structuredClone
會進行深拷貝,但它的行為可能與一些自定義的深拷貝函數有所不同。
這邊附上 structuredClone 一些相關參考跟介紹,有興趣的朋友可以看一下,可以學到蠻多的。
我自己觀察大部分有點資深的工程師比較少會知道 structuredClone 這個 API,畢竟在以前就有好幾種的方式可以處理深拷貝,所以第一時間反應不會去注意到說現在有新的 API 可以幫我們處理深拷貝。
今天就分享這個有用的資訊給各位,但如果你想學習更新更深入的 JavaScript 的話,歡迎你來上我的 JavaScript 課程,我的課程會有更多像是這類的內容以及大量的業界情境範例讓你可以學習到更全面的 JavaScript前端開發技巧。
現在輸入折扣碼:mikemedium (單堂課程折 200元 ,組合包再折 500 元)
有任何問題都可以加我的 line 來詢問我喔 line id : @mike_cheng