一行代碼實現(xiàn)深拷貝?別再用 JSON.stringify 了!
在JavaScript開發(fā)中,對象的深拷貝是一個常見需求。很多開發(fā)者習(xí)慣使用JSON.parse(JSON.stringify(obj))這個"一行代碼"解決方案來實現(xiàn)深拷貝,但這種方法存在許多令人意想不到的問題。本文將揭示這種方法的缺陷,并介紹幾種更可靠的深拷貝替代方案。
一、JSON.stringify 的致命缺陷
JSON.parse(JSON.stringify(obj))看起來簡單優(yōu)雅,但實際上是一個有著嚴重局限性的解決方案。以下是它無法正確處理的情況:
1. 無法處理循環(huán)引用
const obj = { name: "對象" };
obj.self = obj; // 循環(huán)引用
// 拋出錯誤: TypeError: Converting circular structure to JSON
const copy = JSON.parse(JSON.stringify(obj));
一旦對象中存在循環(huán)引用,這種方法就會直接拋出錯誤,導(dǎo)致程序崩潰。
2. 丟失特殊數(shù)據(jù)類型
JSON序列化無法處理函數(shù)、Symbol、undefined,會將Date轉(zhuǎn)為字符串,RegExp變?yōu)榭諏ο螅琋aN和Infinity變?yōu)閚ull。
3. 原型鏈丟失
深拷貝后的對象變成了普通對象,失去了原型鏈上的所有方法和屬性。
4. Map、Set、WeakMap、WeakSet 的處理
這些集合類型在JSON序列化過程中都變成了空對象,數(shù)據(jù)完全丟失。
二、更可靠的深拷貝替代方案
既然JSON方法這么多坑,那么有哪些更好的替代方案呢?現(xiàn)代瀏覽器提供了原生的結(jié)構(gòu)化克隆APIstructuredClone,可以處理大多數(shù)情況:
// 一行代碼實現(xiàn)深拷貝
const copy = structuredClone(original);
優(yōu)點:
- 支持循環(huán)引用
- 支持大多數(shù)內(nèi)置類型(Date、RegExp、Map、Set等)
- 性能優(yōu)于JSON方法
缺點:
- 不支持函數(shù)、DOM節(jié)點、原型鏈
盡管JSON.parse(JSON.stringify(obj))這個"一行代碼"解決方案看起來簡潔優(yōu)雅,但它存在太多缺陷,在實際項目中使用可能會引入意料之外的bug?,F(xiàn)代JavaScript提供了更可靠的深拷貝方案,structuredClone作為原生API是最值得推薦的簡單替代方案。