JavaScript的深克隆和淺克隆

最近在復(fù)習(xí),發(fā)現(xiàn)前端好多知識(shí)點(diǎn)牽一發(fā)動(dòng)全身。
比如我想看一下JQuery的extend源碼,就不得不再好好看看深克隆淺克隆的問題。 ??????


什么是深克???

我們都知道,JavaScript有六種基本的數(shù)據(jù)類型。
五種基本的數(shù)據(jù)類型:string,number,undefined,boolean,null
(在內(nèi)存中表現(xiàn)為一個(gè)值,保存在棧中)
一種復(fù)雜的數(shù)據(jù)類型(引用類型):object 【function,array,object】
(在內(nèi)存中表現(xiàn)為一個(gè)指針,保存在堆中)

將一個(gè)對(duì)象的所有屬性均復(fù)制,并將該對(duì)象與原對(duì)象放在內(nèi)存中不同的位置,此時(shí),改變新對(duì)象的屬性不會(huì)對(duì)原對(duì)象造成影響,這種行為叫做深克隆。


我們還是先看淺克隆吧。。。

    var people= {
        name:"sun",
        age:24,
        hobby:["eat","shopping"],
        son:{
            age:3
        }
    }
//此處為淺克隆
    function extendClone(oldObj) {
        var newObj = {};
        for(var i in oldObj){
            newObj[i] = oldObj[i];
        }
        return newObj;
    }

    console.log(people);
    var people1 = extendClone(people);
    people1.name = "劉某某";
    people1.hobby.push("看?。?);
    console.log(people1);
    var people2 = extendClone(people);
    people2.name = "陳某某";
    people2.hobby.push("游泳!");
    console.log(people2);

看他們的愛好!!.png

淺克隆只是簡(jiǎn)單的復(fù)制對(duì)象,若對(duì)象其中一個(gè)屬性是引用值,由于引用型變量保存的是內(nèi)存的一個(gè)地址,所以后來的hobby屬性,都指向內(nèi)存中的同一塊地址,最后輸出的結(jié)果同樣相同。
從上面的例子也可以看出,name等原始值的改變,并不會(huì)影響原對(duì)象中的原始值。


解決克隆引用值問題,還是需要深度克隆的!

for-in循環(huán)遍歷對(duì)象上的所有屬性,判斷是否為引用值,若是,進(jìn)行遞歸,直到所有屬性都為原始值為止。
拷貝出來后,就是一個(gè)全新對(duì)像,就和之前沒什么關(guān)系了,以前的改變也不能對(duì)新的產(chǎn)生影響!!

var people= {
        name:"sun",
        age:24,
        hobby:["eat","shopping"],
        son:{
            age:3
        }
    }
    function deepClone(oldObj,newObj){
        var newObj = newObj||{};
        for(var i in oldObj){
            if(typeof oldObj[i]==='object'){
                newObj[i] = (oldObj[i].constructor === Array) ? [] : {};//保存克隆后的引用值
                deepClone(oldObj[i],newObj[i]);
            }else {
                newObj[i] = oldObj[i];
            }
        }
        return newObj;
    }
    console.log(people);
    var people1 = deepClone(people);
    people1.name = "劉某某";
    people1.hobby.push("看劇!");
    console.log(people1);
    var people2 = deepClone(people);
    people2.name = "陳某某";
    people2.hobby.push("游泳!");
    console.log(people2);
看他們的愛好??!.png

一些擴(kuò)展

  • concat( )和slice( )
    slice和concat方法都會(huì)返回一個(gè)新的數(shù)組,但是這兩個(gè)方法對(duì)于數(shù)組中的對(duì)象卻沒有執(zhí)行深復(fù)制
    var array = [[1,1,1],{name:"syx"},[3,3,3]];
    var arrSlice = array.slice(0,2);
    console.log(array); //[[1,1,1],{name:"syx"},[3,3,3]];
    console.log(arrSlice);  //[[1,1,1],{name:"syx"}]
    
    此時(shí)看起來好像是深度拷貝了,但是我們修改name值。。。
    arrSlice[1].name = "SYX";
    console.log(array); //[[1,1,1],{name:"SYX"},[3,3,3]];
    console.log(arrSlice);  //[[1,1,1],{name:"SYX"}]
    
    很容易看出,此時(shí)進(jìn)行的是淺復(fù)制
  • jQuery.extend( [deep ], target, object1 [, objectN ] )

deep
類型: Boolean
如果是true,合并成為遞歸(又叫做深拷貝)默認(rèn)值為false,表示淺拷貝。
target
類型: Object
對(duì)象擴(kuò)展。這將接收新的屬性。
object1
類型: Object
一個(gè)對(duì)象,它包含額外的屬性合并到第一個(gè)參數(shù).
objectN
類型: Object
包含額外的屬性合并到第一個(gè)參數(shù)

1.合并兩個(gè)對(duì)象,并修改第一個(gè)對(duì)象

var a= {
            name:"sun",
            age:24,
            hobby:["eat","shopping"],
            son:{
                age:3
            }
        }
        var b= {
            name:"li",
            age:28,
            hobby:["游泳","看劇"],
            son:{
                age:5
            }
        }
   $.extend(a, b);
b覆蓋了a的原有屬性.png

2.當(dāng)繼承的對(duì)象屬性中有引用類型的時(shí)候,兩個(gè)對(duì)象同時(shí)指向一個(gè)對(duì)象,改變一個(gè)另一個(gè)也隨之改變。如果有相同屬性,后邊的會(huì)覆蓋前邊的

var a= {
           name:"sun",
           age:24,
           son:{
               age:3,
               name:"小名"
           }
       }
 var b= {
           son:{
               hobby:'游泳'
           }
       }
$.extend(true,a, b);
console.log(a);
b的新屬性添加到了a上.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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