成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript對象的深淺復(fù)制

B0B0 / 1848人閱讀

摘要:本文是我在復(fù)制對象方面的一些心得總結(jié),由淺復(fù)制到深復(fù)制,由只復(fù)制簡單屬性到復(fù)制,等復(fù)雜屬性,層層遞進(jìn)。如有陳述不當(dāng)之處,煩請指出,不勝感激。下面是一個(gè)簡單的淺復(fù)制實(shí)現(xiàn)。

前言

從層次上來看,對象的復(fù)制可以簡單地分為淺復(fù)制和深復(fù)制,顧名思義,淺復(fù)制是指只復(fù)制一層對象的屬性,不會復(fù)制對象中的對象的屬性,對象的深復(fù)制會復(fù)制對象中層層嵌套的對象的屬性。
在復(fù)制對象時(shí),除了要復(fù)制對象的屬性外,還要兼顧到是否保留了對象的constructor屬性,是否對每一種數(shù)據(jù)類型(JavaScript常見的數(shù)據(jù)類型有String,Number,Boolean,Data,RegExp,Array,Funtion,Object)都實(shí)現(xiàn)正確的復(fù)制。項(xiàng)目中,我們可以根據(jù)實(shí)際情況,決定需要實(shí)現(xiàn)什么樣程度的復(fù)制。
本文是我在復(fù)制對象方面的一些心得總結(jié),由淺復(fù)制到深復(fù)制,由只復(fù)制簡單屬性到復(fù)制Function,RegExp等復(fù)雜屬性,層層遞進(jìn)。如有陳述不當(dāng)之處,煩請指出,不勝感激。

正文 淺復(fù)制

淺復(fù)制只會依次復(fù)制對象的每一個(gè)屬性,不會對這些屬性進(jìn)行遞歸復(fù)制。下面是一個(gè)簡單的淺復(fù)制實(shí)現(xiàn)。

//對象淺復(fù)制                                                           
function shadowCopy(obj){
        if(typeof obj !== "object") return obj;

        for(var prop in obj){
            if(obj.hasOwnProperty(prop)){
                newObj[prop] = obj[prop];
            }
        }
        return newObj;
    }

仔細(xì)觀察,不難發(fā)現(xiàn)上述方法的缺陷:
1.不能正確實(shí)現(xiàn)數(shù)組的淺復(fù)制
2.復(fù)制操作丟失了對象的constructor屬性

好,我們現(xiàn)在已經(jīng)發(fā)現(xiàn)了問題所在,只需針對性地解決,一個(gè)還算完美的淺復(fù)制對象的方法就誕生了!

//對象淺復(fù)制
    function shadowCopy(obj){
            if(typeof obj !== "object") return ;
            var newObj;

            //保留對象的constructor屬性
            if(obj.constructor === Array){
                newObj = [];
            } else {
                newObj = {};
                newObj.constructor = obj.constructor;
            }

            for(var prop in obj){
                if(obj.hasOwnProperty(prop)){
                    newObj[prop] = obj[prop];
                }
            }
            return newObj;
        }

瀏覽器中測試一下:

    var arr1 = [0,1,2];
    console.log(arr1);
    console.log(shadowCopy(arr1));
    
    var arr2 = [0,1,2,[3,4,5]],
        arr2Copy = shadowCopy(arr2);
    console.log(arr2);
    console.log(arr2Copy);
    arr2Copy[3][0] = 6;
    console.log(arr2[3][0]);  //6

Good! 可以正確實(shí)現(xiàn)數(shù)組復(fù)制和并且保留constructor了,但細(xì)心的你一定發(fā)現(xiàn)了,淺復(fù)制后的對象的 arr2Copy[3]arr2[3] 指向的是一個(gè)對象,改變其中一個(gè),同時(shí)也會改變另一個(gè)。我們想要實(shí)現(xiàn)的是 復(fù)制,但這并不是復(fù)制呀!
這是淺復(fù)制的一個(gè)弊端所在,接下讓我們看看深復(fù)制是怎樣解決這個(gè)問題的。

深復(fù)制

深復(fù)制需要層層遞歸,復(fù)制對象的所有屬性,包括對象屬性的屬性的屬性....(暈~)
如果只是需要簡單地復(fù)制對象的屬性,而不用考慮它的constructor,也不用考慮函數(shù),正則,Data等特殊數(shù)據(jù)類型,那這里有一個(gè)深復(fù)制的小trick,兩行代碼即可:

function deepCopy(obj){
    if(typeof obj !== "object"){ return ;}
    var str = JSON.stringify(obj);
    return JSON.parse(str);
}

大多數(shù)情況下,上面的就可以滿足要求了,但一些時(shí)候,我們需要把函數(shù),正則等特殊數(shù)據(jù)類型也考慮在內(nèi),或者當(dāng)前環(huán)境不支持JSON時(shí),上面的方法也就不適用了。這時(shí),我們可以通過遞歸來實(shí)現(xiàn)對象的深層復(fù)制,如下:

function deepCopy(obj){
    if(typeof obj !== "object"){ return ;}
    var newObj;

    //保留對象的constructor屬性
    if(obj.constructor === Array){
        newObj = [];
    } else {
        newObj = {};
        newObj.constructor = obj.constructor;
    }

    for(var prop in obj){
        if(typeof obj[prop] === "object"){
            if(obj[prop].constructor === RegExp ||obj[prop].constructor === Date){
                newObj[prop] = obj[prop];
            } else {
                //遞歸
                newObj[prop] = deepCopy(obj[prop]);
            }
        } else {
            newObj[prop] = obj[prop];
        }
    }
    return newObj;
}

先用上面的例子測試:

棒!可以正確實(shí)現(xiàn)多維數(shù)組的復(fù)制,再看是否能實(shí)現(xiàn)函數(shù)和正則的復(fù)制:

function Person(name){
    this.name = name;
    this.age = age;
    this.search = new RegExp(name);
    this.say = function(){
        console.log(this.name + "今年" + this.age + "歲了");
    }
}
var p1 = new Person("Claiyre",20),
    p2 = deepCopy(p1);

console.log(p1);
console.log(p2);

p2.age = 22;
p1.say();
p2.say();

圓滿完成??!

稍加整理,我們就可以得到一個(gè)較為通用的js對象復(fù)制函數(shù):

function deepCopy(obj){
    var newObj = obj.constructor === Array ? []:{};
    newObj.constructor = obj.constructor;

    if(typeof obj !== "object"){ 
        return ;
    } else if(window.JSON){
        //若需要考慮特殊的數(shù)據(jù)類型,如正則,函數(shù)等,需把這個(gè)else if去掉即可
        newObj = JSON.parse(JSON.stringify(obj));
    } else {
        for(var prop in obj){
            if(obj[prop].constructor === RegExp ||obj[prop].constructor === Date){
                newObj[prop] = obj[prop];
            } else if(typeof obj[prop] === "object"){
                //遞歸
                newObj[prop] = deepCopy(obj[prop]);
            } else {
                newObj[prop] = obj[prop];
            }
        }
    } 
    return newObj;
}
結(jié)語

面向?qū)ο蟮木幊陶Z言,其核心是對象,因此深入了解對象的相關(guān)操作,縱向比較異同,對學(xué)習(xí)過程是極有好處的。

博客原文地址:Claiyre的個(gè)人博客 https://claiyre.github.io/
博客園地址:http://www.cnblogs.com/nuannuan7362/
如需轉(zhuǎn)載,請?jiān)谖恼麻_頭注明原文地址

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/82294.html

相關(guān)文章

  • Javascript對象深淺拷貝

    摘要:開門見山,有人叫對象的復(fù)制為深復(fù)制淺復(fù)制,也有人叫深拷貝淺拷貝。高級屬性修改深拷貝滿足對象的復(fù)制,淺拷貝影響原數(shù)組。關(guān)于對象的深淺拷貝,暫且探索到這里,后續(xù)有新發(fā)現(xiàn)再進(jìn)行補(bǔ)充。 showImg(https://segmentfault.com/img/remote/1460000014305581); 開門見山,有人叫對象的復(fù)制為深復(fù)制淺復(fù)制,也有人叫深拷貝淺拷貝。其實(shí)都是copy。 ...

    qieangel2013 評論0 收藏0
  • 深淺拷貝

    摘要:深復(fù)制實(shí)現(xiàn)代碼如下第一種方法通過遞歸解析解決第二種方法通過解析解決作者六師兄鏈接原生深拷貝的實(shí)現(xiàn)處理未輸入新對象的情況通過方法構(gòu)造新的對象 深淺拷貝針對的是 對象類型,如果是字符串的數(shù)組用[...arr],還是不會影響 要區(qū)分針對數(shù)組的深淺拷貝(默認(rèn)情況為里面沒有對象的數(shù)組),與針對對象的深淺拷貝 JavaScript數(shù)組深拷貝和淺拷貝的兩種方法 let a1 = [1, 2]; ...

    Karrdy 評論0 收藏0
  • 復(fù)習(xí)Javascript專題(四):js中深淺拷貝

    摘要:基本數(shù)據(jù)類型的復(fù)制很簡單,就是賦值操作,所以深淺拷貝也是針對,這類引用類型數(shù)據(jù)。它會拋棄對象的。另外,查資料過程中還看到這么一個(gè)詞結(jié)構(gòu)化克隆算法還有這一篇資料也有參考,也寫得比較詳細(xì)了的深淺拷貝 基本數(shù)據(jù)類型的復(fù)制很簡單,就是賦值操作,所以深淺拷貝也是針對Object,Array這類引用類型數(shù)據(jù)。 淺拷貝對于字符串來說,是值的復(fù)制,而對于對象來說則是對對象地址的復(fù)制;而深拷貝的話,它不...

    MobService 評論0 收藏0
  • JavaScript深淺拷貝

    摘要:基本類型指的是簡單的數(shù)據(jù)段,而引用類型指的是一個(gè)對象保存在堆內(nèi)存中的地址,不允許我們直接操作內(nèi)存中的地址,也就是說不能操作對象的內(nèi)存空間,所以,我們對對象的操作都只是在操作它的引用而已。 工作中經(jīng)常會遇到需要復(fù)制 JavaScript 數(shù)據(jù)的時(shí)候,遇到 bug 時(shí)實(shí)在令人頭疼;面試中也經(jīng)常會被問到如何實(shí)現(xiàn)一個(gè)數(shù)據(jù)的深淺拷貝,但是你對其中的原理清晰嗎?一起來看一下吧! 一、為什么會有深淺...

    Tonny 評論0 收藏0
  • js深淺復(fù)制

    摘要:總結(jié)綜上所述,數(shù)組的深拷貝比較簡單,方法沒有什么爭議,對象的深拷貝,比較好的方法是用的方法實(shí)現(xiàn),或者遞歸實(shí)現(xiàn),比較簡單的深復(fù)制可以使用實(shí)現(xiàn)參考資料知乎中的深拷貝和淺拷貝深入剖析的深復(fù)制 深淺復(fù)制對比 因?yàn)镴avaScript存儲對象都是存地址的,所以淺復(fù)制會導(dǎo)致 obj 和obj1 指向同一塊內(nèi)存地址。我的理解是,這有點(diǎn)類似數(shù)據(jù)雙向綁定,改變了其中一方的內(nèi)容,都是在原來的內(nèi)存基礎(chǔ)上做...

    Apollo 評論0 收藏0

發(fā)表評論

0條評論

B0B0

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<