JavaScript?深拷貝的循環(huán)引用問(wèn)題詳解
如果說(shuō)道實(shí)現(xiàn)深拷貝最簡(jiǎn)單的方法,我們第一個(gè)想到的就是 JSON.stringify() 方法,因?yàn)镴SON.stringify()后返回的是字符串,所以我們會(huì)再使用JSON.parse()轉(zhuǎn)換為對(duì)象,如下代碼:
let obj = { name: 'liaoyi',age: 22,sex: 1} JSON.parse(JSON.stringify(obj))
但是這種克隆不夠完美,有一個(gè)致命的問(wèn)題無(wú)法解決,就是她一旦遇到循環(huán)引用就會(huì)報(bào)錯(cuò):
let obj = { name: 'liaoyi',age: 22,sex: 1} JSON.parse(JSON.stringify(obj)) obj.c = obj console.log(JSON.stringify(obj))
js會(huì)報(bào)錯(cuò),無(wú)法把一個(gè)循環(huán)引用轉(zhuǎn)成 json 格式:
在這種情況下,我們通常想到的是寫(xiě)一個(gè)正兒八經(jīng)的深度克隆方法:
使用傳統(tǒng)方式實(shí)現(xiàn)對(duì)象的深拷貝
function deepClone(obj) { const objectMap = new Map(); const _deepClone = value => { const type = typeof value; if (type !== 'object' || type === null) { return value; } if (objectMap.has(value)) { return objectMap.get(value); } const result = Array.isArray(value) ? [] : {}; objectMap.set(value, result); for (const [key, _v] of Object.entries(value)) { result[key] = _deepClone(value[key]); console.log(key, _v); } return result; }; return _deepClone(obj); }
使用 MessageChannel 實(shí)現(xiàn)循環(huán)引用對(duì)象的深拷貝
不夠新鮮,我們來(lái)看一個(gè)好玩的 Web API
參考鏈接: MessageChannel
MessageChannel允許我們?cè)诓煌臑g覽上下文,比如window.open()打開(kāi)的窗口或者iframe等之間建立通信管道,并通過(guò)兩端的端口(port1和port2)發(fā)送消息。MessageChannel以DOM Event的形式發(fā)送消息,所以它屬于異步的宏任務(wù)。
// 通過(guò)這個(gè)構(gòu)造函數(shù),創(chuàng)建一個(gè)消息通道,它會(huì)返回一個(gè)對(duì)象,解構(gòu) port1, port2 來(lái)實(shí)現(xiàn)通信 const { port1, port2 } = new MessageChannel(); port1.postMessage('hello') port2.onmessage = msg => { console.log(msg.data) // hello }
我們可以利用這個(gè)API,實(shí)現(xiàn)循環(huán)引用對(duì)象的深拷貝:
function deepClone(obj) { return new Promise(resolve => { const { port1, port2 } = new MessageChannel(); port1.postMessage(obj); port2.onmessage = msg => { resolve(msg.data); // console.log(obj, msg.data === obj); // false }; }) } const obj = { a: 1, b: '2' } obj.c = obj; deepClone(obj).then(res =>{ console.log('res',res); })
到此這篇關(guān)于JavaScript 深拷貝的循環(huán)引用問(wèn)題 _的文章就介紹到這了,更多相關(guān)JavaScript 深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序動(dòng)畫(huà)(Animation)的實(shí)現(xiàn)及執(zhí)行步驟
這篇文章主要介紹了微信小程序動(dòng)畫(huà)(Animation) 的實(shí)現(xiàn)及執(zhí)行步驟,需要的朋友可以參考下2018-10-10JS模態(tài)窗口返回值兼容問(wèn)題的完美解決方法
下面小編就為大家?guī)?lái)一篇JS模態(tài)窗口返回值兼容問(wèn)題的完美解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05js和jquery中循環(huán)的退出和繼續(xù)下一個(gè)循環(huán)
退出循環(huán),使用break;退出當(dāng)前循環(huán)繼續(xù)下一個(gè)循環(huán),使用continue,jquery中使用return false;continue,使用return true2014-09-09微信小程序wxs日期時(shí)間處理的實(shí)現(xiàn)示例
最近在做一個(gè)列表的時(shí)候,涉及到時(shí)間格式化操作。本文主要介紹了微信小程序wxs日期時(shí)間處理的實(shí)現(xiàn)示例,分享給大家,感興趣的可以了解一下2021-07-07avaScript基礎(chǔ)學(xué)習(xí)-基本的語(yǔ)法規(guī)則
這篇文章主要介紹了avaScript的語(yǔ)法規(guī)則,本文的語(yǔ)法講解主要講一下與其他語(yǔ)言的區(qū)別,下面詳細(xì)的介紹內(nèi)容,需要的小伙伴可以參考一下,希望對(duì)你有所幫助2022-02-02js+audio實(shí)現(xiàn)音樂(lè)播放器
這篇文章主要為大家詳細(xì)介紹了js+audio實(shí)現(xiàn)音樂(lè)播放器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09JS如何實(shí)現(xiàn)文本框隨文本的長(zhǎng)度而增長(zhǎng)
這篇文章主要介紹了JS如何實(shí)現(xiàn)文本框隨文本的長(zhǎng)度而增長(zhǎng)的方法,具有一定借鑒價(jià)值,需要的朋友可以參考下2015-07-07