JavaScript使用structuredClone實(shí)現(xiàn)深拷貝
前言
在JavaScript中,實(shí)現(xiàn)深拷貝的方式有很多種,每種方式都有其優(yōu)點(diǎn)和缺點(diǎn)。今天介紹一種原生JavaScript提供的structuredClone
實(shí)現(xiàn)深拷貝。
下面列舉一些常見的方式,以及它們的代碼示例和優(yōu)缺點(diǎn):
1. 使用JSON.parse(JSON.stringify(obj))
代碼示例:
function deepClone(obj) { return JSON.parse(JSON.stringify(obj)); }
優(yōu)點(diǎn):簡(jiǎn)單易行,對(duì)于大多數(shù)對(duì)象類型有效。
缺點(diǎn):不能復(fù)制原型鏈,對(duì)于包含循環(huán)引用的對(duì)象可能出現(xiàn)問題。比如以下代碼:
const calendarEvent = { date: new Date() } const problematicCopy = JSON.parse(JSON.stringify(calendarEvent))
最終得到的date不是Data對(duì)象,而是字符串。
{ "date": "2024-03-02T03:43:35.890Z" }
這是因?yàn)?code>JSON.stringify只能處理基本的對(duì)象、數(shù)組。任何其他類型都沒有按預(yù)期處理。例如,日期轉(zhuǎn)換為字符串。Set/Map只是轉(zhuǎn)換為{}
。
const kitchenSink = { set: new Set([1, 3, 3]), map: new Map([[1, 2]]), regex: /foo/, deep: { array: [ new File(someBlobData, 'file.txt') ] }, error: new Error('Hello!') } const veryProblematicCopy = JSON.parse(JSON.stringify(kitchenSink))
最終得到如下數(shù)據(jù):
{ "set": {}, "map": {}, "regex": {}, "deep": { "array": [ {} ] }, "error": {}, }
2. 使用遞歸
代碼示例:
function deepClone(obj) { if (obj === null || typeof obj !== 'object') { return obj; } let clone = obj.constructor(); for (let attr in obj) { if (obj.hasOwnProperty(attr)) { clone[attr] = this.deepClone(obj[attr]); } } return clone; }
優(yōu)點(diǎn):對(duì)于任何類型的對(duì)象都有效,包括循環(huán)引用。
缺點(diǎn):對(duì)于大型對(duì)象可能會(huì)消耗大量?jī)?nèi)存,并可能導(dǎo)致堆棧溢出。
3. 第三方庫,如 lodash 的 _.cloneDeep 方法
代碼示例:
const _ = require('lodash'); function deepClone(obj) { return _.cloneDeep(obj); }
優(yōu)點(diǎn):支持更多類型的對(duì)象和庫,例如,支持 Proxy 對(duì)象。
缺點(diǎn):會(huì)引入依賴導(dǎo)致項(xiàng)目體積增大。
因?yàn)檫@個(gè)函數(shù)會(huì)導(dǎo)致17.4kb的依賴引入,如果只是引入lodash會(huì)更高。
4. 現(xiàn)代深拷貝structuredClone
在現(xiàn)代瀏覽器中,可以使用 structuredClone
方法來實(shí)現(xiàn)深拷貝,它是一種更高效、更安全的深拷貝方式。
以下是一個(gè)示例代碼,演示如何使用 structuredClone
進(jìn)行深拷貝:
const kitchenSink = { set: new Set([1, 3, 3]), map: new Map([[1, 2]]), regex: /foo/, deep: { array: [ new File(someBlobData, 'file.txt') ] }, error: new Error('Hello!') } kitchenSink.circular = kitchenSink const clonedSink = structuredClone(kitchenSink)
structuredClone
可以做到:
- 拷貝無限嵌套的對(duì)象和數(shù)組
- 拷貝循環(huán)引用
- 拷貝各種各樣的JavaScript類型,如
Date
、Set
、Map
、Error
、RegExp
、ArrayBuffer
、Blob
、File
、ImageData
等
哪些不能拷貝:
- 函數(shù)
- DOM節(jié)點(diǎn)
- 屬性描述、
setter
和getter
- 對(duì)象原型鏈
所支持的完整列表:
Array
、ArrayBuffer
、Boolean
、DataView
、Date
、Error
類型(下面具體列出的類型)、Map
、Object
,但僅限于普通對(duì)象、原始類型,除了symbol
(又名number
、string
、null
、undefined
、boolean
、BigInt
)、RegExp
、Set
、TypedArray
Error類型:
Error
, EvalError
, RangeError
, ReferenceError
, SyntaxError
, TypeError
, URIError
Web/API類型:
AudioData
, Blob
, CryptoKey
, DOMException
, DOMMatrix
, DOMMatrixReadOnly
, DOMPoint
, DomQuad
, DomRect
, File
, FileList
, FileSystemDirectoryHandle
, FileSystemFileHandle
, FileSystemHandle
, ImageBitmap
, ImageData
, RTCCertificate
, VideoFrame
值得慶幸的是 structuredClone
在所有主流瀏覽器中都受支持,也支持Node.js和Deno。
最后
我們現(xiàn)在終于可以直接使用原生JavaScript中的structuredClone
能力實(shí)現(xiàn)深度拷貝對(duì)象。每種方式都有其優(yōu)缺點(diǎn),具體使用方式取決于你的需求和目標(biāo)對(duì)象的類型。
以上就是JavaScript使用structuredClone實(shí)現(xiàn)深拷貝的詳細(xì)內(nèi)容,更多關(guān)于JavaScript structuredClone深拷貝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript利用Date實(shí)現(xiàn)簡(jiǎn)單的倒計(jì)時(shí)實(shí)例
在日常開發(fā)的時(shí)候經(jīng)常遇到關(guān)于倒計(jì)時(shí)的需求,下面這篇文章就給主要介紹了JavaScript利用Date實(shí)現(xiàn)倒計(jì)時(shí)效果的方法示例,文中主要實(shí)現(xiàn)了倒計(jì)時(shí)和倒計(jì)時(shí)結(jié)束搶購(gòu)的按鈕才可以被點(diǎn)擊的效果,有需要的朋友可以參考借鑒。2017-01-01html中鼠標(biāo)滾輪事件onmousewheel的處理方法
下面小編就為大家?guī)硪黄猦tml中鼠標(biāo)滾輪事件onmousewheel的處理方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11JS實(shí)現(xiàn)數(shù)組扁平化的8種方式總結(jié)
數(shù)組扁平化指的是將一個(gè)多層嵌套的數(shù)組,處理成只有一層的數(shù)組,本文為大家整理了8個(gè)常用的JS實(shí)現(xiàn)數(shù)組扁平化的方法,希望對(duì)大家有所幫助2023-08-08基于javascript實(shí)現(xiàn)簡(jiǎn)單的抽獎(jiǎng)系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于javascript實(shí)現(xiàn)簡(jiǎn)單的抽獎(jiǎng)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03JavaScript實(shí)現(xiàn)數(shù)值自動(dòng)增加動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)數(shù)值自動(dòng)增加動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12JavaScript實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)表格
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)表格,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12JavaScript實(shí)現(xiàn)彈窗效果代碼分析
本文主要介紹了JavaScript實(shí)現(xiàn)彈窗效果的代碼分析,具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-03-03微信小程序使用form表單獲取輸入框數(shù)據(jù)的實(shí)例代碼
這篇文章主要介紹了微信小程序使用form表單獲取輸入框數(shù)據(jù)的實(shí)例代碼,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05js實(shí)現(xiàn)省市聯(lián)動(dòng)效果的簡(jiǎn)單實(shí)例
本篇文章主要是對(duì)js實(shí)現(xiàn)省市聯(lián)動(dòng)效果的簡(jiǎn)單實(shí)例進(jìn)行了介紹,需要的朋友可以過來,希望對(duì)大家有所幫助2014-02-02