深拷貝和淺拷貝

深復(fù)制和淺復(fù)制只針對像 Object, Array 這樣的復(fù)雜對象。簡單來說,淺復(fù)制只復(fù)制一層對象的屬性,而深復(fù)制則遞歸復(fù)制了所有層級。

一、淺拷貝

let obj = {a: 1, b: [2,3]}
function shadowCopy (obj) {
    var newObj = {};
    for(let prop in obj) {
        if(obj.hasOwnProperty(prop)) {
            newObj[prop] = obj[prop];
        }
    }
    return newObj;
}
let shadowObj = shadowCopy(obj);

因?yàn)闇\復(fù)制只會將對象的各個屬性進(jìn)行依次復(fù)制,并不會進(jìn)行遞歸復(fù)制。而 JavaScript 存儲對象都是存地址的,所以淺復(fù)制會導(dǎo)致 obj.arr 和 shadowObj.arr 指向同一塊內(nèi)存地址。

二、深拷貝

  • 深拷貝則是復(fù)制變量值,對于非基本類型的變量,則遞歸至基本類型變量后,再復(fù)制。它不僅將原對象的各個屬性逐個復(fù)制出去,而且將原對象各個屬性所包含的對象也依次采用深復(fù)制的方法遞歸復(fù)制到新對象上。這就不會存在上面 obj 和 shadowObj 的 arr 屬性指向同一個對象的問題。
let simpleObj = {
    a:1,
    b:{
        b1:1
    },
    c:[
        {
            c1:1
        }
    ]
 };
let simpleArr=[
    {
        a:[1,2,3]
    },
    {
        b:1
    },
    {
        p:[1,2]
    }
 ]
let deepCopy = function (targetObj) {
    let copiedObj = Array.isArray(targetObj) ? [] : {};
    let ArrayDealer = function(arrayVal, copiedObj) {
        arrayVal.forEach(function(arrVal, index) {
            copiedObj[index] = {};
            console.log(arrVal);
            if(typeof arrVal == 'object') {
                copy(arrval[index], copiedObj[index]);
            }else{
                copiedObj[index] = arrVal;
            }
        })
    };
    let ObjectDealer = function (targetObj, copiedObj) {
        for(var key in targetObj) {
            var val = targetObj[key];
            copiedObj[key] = {};
            //非引用類型節(jié)點(diǎn)
            if(typeof val=='object'){
                copy(val,copiedObj[key]);
            }else{
               copiedObj[key] = val;
            }
        }
    }
    let copy = function (targetObj, copiedObj) {
        if(Array.isArray(targetObj)) {
            ArrayDealer(targetObj, copiedObj);
        }else{
            ObjectDealer(targetObj, copiedObj);
        }
    }
    copy(targetObj, copiedObj);
    return copiedObj; 
}
console.log(deepCopy(simpleObj));
console.log(deepCopy(simpleArr));
  • 還有一種方法是借助JSON 全局對象,針對純 JSON 數(shù)據(jù)對象的深復(fù)制,正確處理的對象只有 Number, String, Boolean, Array, 扁平對象,即那些能夠被 json 直接表示的數(shù)據(jù)結(jié)構(gòu)。
    下面的例子是深拷貝對象和數(shù)組。
var cloneObj = function(obj){
    var str, newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== 'object'){
        return;
    } else if(window.JSON){
        str = JSON.stringify(obj), //系列化對象
        newobj = JSON.parse(str); //還原
    } else {
        for(var i in obj){
            newobj[i] = typeof obj[i] === 'object' ? 
            cloneObj(obj[i]) : obj[i]; 
        }
    }
  • 也可以用jQuery的extend
var x = {
    a: 1,
    b: { f: { g: 1 } },
    c: [ 1, 2, 3 ]
};

var y = $.extend({}, x),          //shallow copy
    z = $.extend(true, {}, x);    //deep copy

y.b.f === x.b.f       // true
z.b.f === x.b.f       // false
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容