JavaScript 處理深拷貝的全新API!

Mike
I am Mike
Published in
6 min readJan 23, 2024

在撰寫 JS 的時候我們很常會對物件去進行深拷貝的處理,我們常見的深拷貝有三種做法,除了常見的做法以外,我還會額外介紹一個全新處裡深拷貝的方法。

關於淺拷貝跟深拷貝網路上已經有許多介紹文章了,這邊暫時不多做贅述!

  1. 使用JSON.parse(JSON.stringify(obj)):
const obj2 = JSON.parse(JSON.stringify(obj1));

這是最簡單的深拷貝方法,但所有非JSON支持的類型都將被忽略或轉換,日期會被轉換為字串,正規表達式會被丟棄。但是它的整體效能快,非常適合使用在小型且簡單的物件身上。

2. 使用lodashcloneDeep

身為前端開發中的老牌子,第三方資料處理的套件, 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 也不是完美的,它也有一些限制

  1. 函數無法複製:就像大多數的深拷貝方法一樣,structuredClone 不能複製函數。
  2. 某些物件型別不支持:雖然 structuredClone 支持許多內建的JavaScript type,但它並不支持複製某些特殊類型的物件,比如 ErrorFunction等。
  3. 瀏覽器支援度:雖然現代瀏覽器大多支持 structuredClone,但在一些舊版本的瀏覽器中可能不支援。如果你的網站支援較舊瀏覽器,可能需要考慮其他替代方案。
  4. 轉換特殊類型時的行為差異:對於一些特殊類型的對象,比如 MapSetArrayBufferDataView 等,structuredClone 會進行深拷貝,但它的行為可能與一些自定義的深拷貝函數有所不同。

這邊附上 structuredClone 一些相關參考跟介紹,有興趣的朋友可以看一下,可以學到蠻多的。

我自己觀察大部分有點資深的工程師比較少會知道 structuredClone 這個 API,畢竟在以前就有好幾種的方式可以處理深拷貝,所以第一時間反應不會去注意到說現在有新的 API 可以幫我們處理深拷貝。

今天就分享這個有用的資訊給各位,但如果你想學習更新更深入的 JavaScript 的話,歡迎你來上我的 JavaScript 課程,我的課程會有更多像是這類的內容以及大量的業界情境範例讓你可以學習到更全面的 JavaScript前端開發技巧。

現在輸入折扣碼:mikemedium (單堂課程折 200元 ,組合包再折 500 元)

有任何問題都可以加我的 line 來詢問我喔 line id : @mike_cheng

--

--

Mike
I am Mike

如果有一行code無法解決的bug,那就寫兩行!