中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Javascript深度克隆中的循環引用問題怎么解決

發布時間:2022-03-03 10:55:46 來源:億速云 閱讀:172 作者:iii 欄目:web開發

這篇文章主要介紹“Javascript深度克隆中的循環引用問題怎么解決”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Javascript深度克隆中的循環引用問題怎么解決”文章能幫助大家解決問題。

概要

在前端項目開發中,我們經常需要深度克隆JS對象。在克隆代碼開發過程中,我們經常會遇到數組判定或對象循環引用的問題。

本文通過實例來解決上述問題

代碼及實現

常見深度克隆JS對象的代碼

function deepClone(origin){

    if (origin == undefined || typeof origin !== "object"){

        return origin;

    }

    if (origin instanceof Date){

        return new Date(origin);

    }

    let keys = Reflect.ownKeys(origin);

    let target = {};

    if (Object.prototype.toString.call(origin) === "[object Array]"){

        target = [];

    }

    for(let key of keys){

        target[key] = deepClone(origin[key]);

    }

    return target;

上述代碼主要存在兩個問題:

數組判定代碼過于麻煩

對象中如果出現循環引用,代碼將會報錯。

循環引用代碼:

var obj = {a: 1};

obj.obj1 = obj;

var newObj = deepClone(obj);

console.log(newObj);

錯誤信息:

產生錯誤的原因很簡單,由于對象中存在循環引用,所以遞歸無法結束,最后內存溢出了。

循環引用問題的解決

由于對象中的循環引用,所以遞歸無法結束。如果我們記錄下哪個對象被克隆了,哪個對象沒有被克隆,就可以強制結束遞歸,避免內存泄漏。

我們選擇WeekMap來記錄對象是否被克隆,主要考慮以下三點:

WeakMap對象是key => value形式,不會重復記錄

WeakMap對象的key必須是一個對象

WeakMap是若引用,如果不再使用,內存空間直接釋放。

改進代碼如下:

function deepClone(origin, map = new WeakMap()){

    if (origin == undefined || typeof origin !== "object"){

        return origin;

    }

    if (origin instanceof Date){

        return new Date(origin);

    }

    if (origin instanceof RegExp){

        return new RegExp(origin);

    }

    var copied = map.get(origin);

    if (!!copied){

        return copied;

    }   

    let target = {};

    if (Object.prototype.toString.call(origin) === "[object Array]"){

        target = [];

    }

    map.set(origin, target);

    let keys = Reflect.ownKeys(origin);

    for(let key of keys){   

        target[key] = deepClone(origin[key], map);

    }

    return target;

通過WeakMap記錄對象是否被拷貝過,如果拷貝過,就直接將拷貝過的對象返回,不再重復克隆

如果沒有被拷貝過,構建數組或普通JS對象,然后再進行記錄。

克隆存在循環引用的對象,代碼如下:

var obj = {a: 1};

obj.obj1 = obj;

var newObj = deepClone(obj);

console.log(newObj);

執行結果如下:

數組判定的代碼優化

在克隆之前,我們必須知道要克隆的對象是一個普通JS對象還是一個數組。我們是否可以換一個思路,任何對象都有自己的構建器,如果我們直接使用構造器構造對象,也就不需要之前對象是什么類型了。

JS中所有對象都有自己的原型鏈,原型鏈中包含基類Object的構造器,如下所示:

JS普通對象

JS數組:

JS普通對象的構造方法可以構建出{},JS數組的構建方法可以構造出[]。所以如果我們調用該構造方法,就無需再去判定數組還是普通對象了。

改進后的代碼如下:

function deepClone(origin, map = new WeakMap()){

    if (origin == undefined || typeof origin !== "object"){

        return origin;

    }

    if (origin instanceof Date){

        return new Date(origin);

    }

    var copied = map.get(origin);

    if (!!copied){

        return copied;

    }   

    let target = new origin.constructor();

    map.set(origin, target);

    let keys = Reflect.ownKeys(origin);

    for(let key of keys){   

        target[key] = deepClone(origin[key], map);

    }

    return target;

關于“Javascript深度克隆中的循環引用問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

景谷| 广东省| 桐乡市| 宁远县| 枣庄市| 临武县| 崇文区| 永登县| 易门县| 应用必备| 四会市| 浮山县| 巨鹿县| 珠海市| 阿合奇县| 抚顺市| 贵溪市| 平原县| 双柏县| 西和县| 高陵县| 疏附县| 通道| 怀柔区| 时尚| 武定县| 文山县| 西安市| 苍山县| 河北省| 邵阳市| 逊克县| 宿迁市| 河北区| 兴山县| 普陀区| 永福县| 花莲市| 兰溪市| 贺州市| 大同县|