JavaScript新特性structuredClone()深拷貝策略詳解
JavaScript新特性structuredClone(),一行代碼優(yōu)化深拷貝策略
structuredClone()使用起來(lái)非常簡(jiǎn)單:
const cloned = structuredClone(obj);
替代:
const cloned = JSON.parse(JSON.stringify(obj));
想知道structuredClone()除了深拷貝以外,還有哪些JSON.parse(JSON.stringify(obj))所沒(méi)有的功能嗎?比起JSON.parse(JSON.stringify(obj))有什么性能上的提升嗎?structuredClone()的環(huán)境限制有哪些?
本文會(huì)告訴你答案。
一、structuredClone()介紹
1、structuredClone()是什么
structuredClone() 是瀏覽器和 Node.js 的原生 API,底層使用更高效的 C++ 實(shí)現(xiàn),比起 JS 層的 JSON.stringify/parse 組合,性能通常更好。
在結(jié)構(gòu)復(fù)雜/嵌套多時(shí)差異更明顯,不需要轉(zhuǎn)成字符串再解析,避免了冗余的編碼/解碼過(guò)程。
2、structuredClone()環(huán)境支持
在 Node.js 17+、Chrome 98+、Firefox 94+ 中支持。
3、structuredClone()不會(huì)拷貝的內(nèi)容
| 不支持或無(wú)法克隆的類型/結(jié)構(gòu) | 說(shuō)明 |
|---|---|
函數(shù) (Function) | 無(wú)法克隆函數(shù)或方法 |
| Symbol | Symbol 屬性會(huì)被忽略 |
| 類實(shí)例的方法/原型鏈 | 原型鏈不會(huì)保留,克隆后不是原類的實(shí)例 |
| DOM 節(jié)點(diǎn)(如 Element、Node) | 不支持 DOM 對(duì)象(比如瀏覽器中的 HTML 元素) |
| Proxy 對(duì)象 | 無(wú)法克隆代理對(duì)象(Proxy) |
| WeakMap / WeakSet | 因其不可枚舉和弱引用特性,無(wú)法被克隆 |
| 函數(shù)作用域內(nèi)的閉包變量 | 本質(zhì)上函數(shù)不能克隆,因此也無(wú)法保留閉包 |
| 不可序列化的 host 對(duì)象 | 如瀏覽器特有的某些對(duì)象(如 Window, FileList) |
4、基礎(chǔ)案例
structuredClone()支持Map、Set、Blob、Date、File等JSON.parse(JSON.stringify(obj))不支持的類型:
const original = {
// 原始類型
string: 'Hello',
number: 123,
boolean: true,
null: null,
undefined: undefined, // JSON會(huì)丟失,structuredClone保留
// 日期對(duì)象 (JSON會(huì)轉(zhuǎn)為字符串,structuredClone保持為Date對(duì)象)
date: newDate('2023-06-15'),
// 正則表達(dá)式 (JSON會(huì)轉(zhuǎn)為空對(duì)象,structuredClone保持為RegExp對(duì)象)
regex: /pattern/g,
// 集合類型
map: newMap([['key', 'value']]),
set: newSet([1, 2, 3]),
// 二進(jìn)制數(shù)據(jù)
arrayBuffer: newUint8Array([1, 2, 3]).buffer,
typedArray: newUint8Array([1, 2, 3]),
// 嵌套數(shù)組和對(duì)象
array: [1, 2, { nested: true }],
object: { nested: { deep: true } }
};
const clone = structuredClone(original);
// 驗(yàn)證類型保持一致
console.log(clone.date instanceof Date); // true
console.log(clone.regex instanceof RegExp); // true
console.log(clone.map instanceof Map); // true
console.log(clone.set instanceof Set); // true
console.log(clone.arrayBuffer instanceof ArrayBuffer); // true
console.log(clone.typedArray instanceof Uint8Array); // true
const clone2 = JSON.parse(JSON.stringify(original));
console.log(clone2.date instanceof Date); // false (變成字符串)
console.log(clone2.set instanceof Set); // false (變成數(shù)組)5、structuredClone()的兼容性判斷
可以用如下代碼安全使用 structuredClone(),在不支持的環(huán)境里自動(dòng)回退到 JSON 方案(雖然功能會(huì)弱一些):
function deepClone(obj) {
if (typeof structuredClone === 'function') {
return structuredClone(obj);
} else {
// fallback: JSON 克?。ㄗ⒁夤δ苡邢蓿?
return JSON.parse(JSON.stringify(obj));
}
}二、 structuredClone()比JSON.parse(JSON.stringify(obj))有什么區(qū)別
1、對(duì)比表格
| 特性 | JSON.parse(JSON.stringify(obj)) | structuredClone(obj) |
|---|---|---|
| 深拷貝 | 是 | 是 |
| 性能 | 較慢(中間需要序列化+解析) | 更快(原生實(shí)現(xiàn)) |
| 支持循環(huán)引用 | 報(bào)錯(cuò) | 支持 |
| 支持類型豐富度 | 僅支持普通對(duì)象、數(shù)組、字符串、數(shù)字、布爾、null | 支持更多類型(Map、Set、Blob、Date、File 等) |
| 丟失信息 | 會(huì)丟失函數(shù)、undefined、Symbol、日期、原型鏈等 | 保留更多原始結(jié)構(gòu) |
| 錯(cuò)誤處理 | 易錯(cuò)(如循環(huán)引用會(huì)直接拋錯(cuò)) | 更安全,報(bào)錯(cuò)更明確 |
2、循環(huán)引用
循環(huán)引用是對(duì)象內(nèi)部相互引用,形成“閉環(huán)”的結(jié)構(gòu),比如:
const obj = {};
obj.self = obj;
const cloned = structuredClone(obj); 如果用 JSON.stringify(obj) 就會(huì)報(bào)錯(cuò):TypeError: Converting circular structure to JSON。但 structuredClone() 就能正確處理
三、structuredClone()在性能上的提升
根據(jù)多個(gè)社區(qū)實(shí)測(cè) benchmark(如 ?JSBench.me?、V8 團(tuán)隊(duì) blog 和真實(shí)項(xiàng)目測(cè)試):
- 深層嵌套對(duì)象(10層以上):structuredClone() 明顯更快;
- 包含 Map、Set、Date、ArrayBuffer 的復(fù)雜對(duì)象:structuredClone() 能直接處理,而 JSON 克隆則需要額外轉(zhuǎn)換或報(bào)錯(cuò);
- 平均測(cè)試中 structuredClone() 比 JSON 快 1.5~5 倍,尤其在大型對(duì)象上提升更顯著。
四、結(jié)語(yǔ)
目前,structuredClone() 已被所有主流瀏覽器支持。它為深拷貝問(wèn)題提供了一個(gè)簡(jiǎn)單、高效的解決方案,快來(lái)?yè)肀н@個(gè)JavaScript新特性吧。
到此這篇關(guān)于JavaScript新特性structuredClone()深拷貝策略詳解的文章就介紹到這了,更多相關(guān)js structuredClone()深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript canvas實(shí)現(xiàn)俄羅斯方塊游戲
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
深入理解JavaScript系列(31):設(shè)計(jì)模式之代理模式詳解
這篇文章主要介紹了深入理解JavaScript系列(31):設(shè)計(jì)模式之代理模式詳解,代理模式使得代理對(duì)象控制具體對(duì)象的引用,代理幾乎可以是任何對(duì)象:文件,資源,內(nèi)存中的對(duì)象,或者是一些難以復(fù)制的東西,需要的朋友可以參考下2015-03-03
詳解如何在Canvas上實(shí)現(xiàn)坐標(biāo)定位
這篇文章我們將來(lái)詳細(xì)的給大家講解一下如何在 canvas 上實(shí)現(xiàn)坐標(biāo)的定位,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2023-08-08
javascript form 驗(yàn)證函數(shù) 彈出對(duì)話框形式
javascript合法驗(yàn)證 js數(shù)據(jù)驗(yàn)證、js email驗(yàn)證、js url驗(yàn)證、js長(zhǎng)度驗(yàn)證、js數(shù)字驗(yàn)證等(彈出對(duì)話框形式)2009-06-06
layui 圖片上傳+表單提交+ Spring MVC的實(shí)例
今天小編就為大家分享一篇layui 圖片上傳+表單提交+ Spring MVC的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09

