JavaScript?深拷貝的循環(huán)引用問題詳解
如果說道實(shí)現(xià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è)致命的問題無法解決,就是她一旦遇到循環(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ò),無法把一個(gè)循環(huán)引用轉(zhuǎn)成 json 格式:

在這種情況下,我們通常想到的是寫一個(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ì)象的深拷貝
不夠新鮮,我們來看一個(gè)好玩的 Web API
參考鏈接: MessageChannel
MessageChannel允許我們?cè)诓煌臑g覽上下文,比如window.open()打開的窗口或者iframe等之間建立通信管道,并通過兩端的端口(port1和port2)發(fā)送消息。MessageChannel以DOM Event的形式發(fā)送消息,所以它屬于異步的宏任務(wù)。
// 通過這個(gè)構(gòu)造函數(shù),創(chuàng)建一個(gè)消息通道,它會(huì)返回一個(gè)對(duì)象,解構(gòu) port1, port2 來實(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)引用問題 _的文章就介紹到這了,更多相關(guān)JavaScript 深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript頁面倒計(jì)時(shí)功能完整示例
這篇文章主要介紹了JavaScript頁面倒計(jì)時(shí)功能,結(jié)合完整實(shí)例形式分析了javascript計(jì)時(shí)器、時(shí)間運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
JavaScript實(shí)現(xiàn)使用Canvas繪制圖形的基本教程
本篇文章主要介紹了JavaScript實(shí)現(xiàn)使用Canvas繪制圖形的基本教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-10-10
CocosCreator Typescript制作俄羅斯方塊游戲
目前關(guān)于cocos開發(fā)俄羅斯方塊的文章幾乎寥寥無幾,因此本文將主要介紹如何通過CocosCreator Typescript制作簡單的俄羅斯方塊游戲,代碼具有一定價(jià)值,感興趣的同學(xué)可以學(xué)習(xí)一下2021-11-11
js與jquery獲取父級(jí)元素,子級(jí)元素,兄弟元素的實(shí)現(xiàn)方法
本篇文章主要是對(duì)js與jquery獲取父級(jí)元素,子級(jí)元素,兄弟元素的實(shí)現(xiàn)方法進(jìn)行了介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-01-01
Javascript訪問Promise對(duì)象返回值的操作方法
這篇文章介紹了如何在JavaScript中使用Promise對(duì)象來處理異步操作,通過使用fetch()方法和Promise對(duì)象,我們可以從后端API獲取數(shù)據(jù)并處理返回值,文章展示了如何使用.then()鏈?zhǔn)讲僮骱蚢sync/await語法來訪問Promise對(duì)象的返回值,感興趣的朋友一起看看吧2025-03-03

