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

資訊專欄INFORMATION COLUMN

JavaScript中的淺拷貝與深拷貝

546669204 / 1766人閱讀

摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。

為什么會(huì)有淺拷貝與深拷貝
什么是淺拷貝與深拷貝
如何實(shí)現(xiàn)淺拷貝與深拷貝
好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧!

如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處,還請(qǐng)看到的小伙伴多多指教,先行謝過(guò)

以下↓

數(shù)據(jù)類型
在開始了解 淺拷貝 與 深拷貝 之前,讓我們先來(lái)回顧一下 JavaScript 的數(shù)據(jù)類型(可以參考這里 JavaScript中的數(shù)據(jù)類型)

在 JavaScript 中,我們將數(shù)據(jù)分為 基本數(shù)據(jù)類型(原始值) 與 引用類型

基本數(shù)據(jù)類型的值是按值訪問(wèn)的,基本類型的值是不可變的
引用類型的值是按引用訪問(wèn)的,引用類型的值是動(dòng)態(tài)可變的
由于數(shù)據(jù)類型的訪問(wèn)方式不同,它們的比較方式也是不一樣的

var a = 100;
var b = 100;

a === b // true

var c = {a: 1, b: 2};
var d = {a: 1, b: 2};

c == d // false 兩個(gè)不同的對(duì)象

·基本數(shù)據(jù)類型的比較是值得比較
·引用類型的比較是引用地址的比較

鑒于以上數(shù)據(jù)類型的特點(diǎn),我們可以初步想到:所謂 淺拷貝 與 深拷貝 可能就是對(duì)于值的拷貝和引用的拷貝(簡(jiǎn)單數(shù)據(jù)類型都是對(duì)值的拷貝,不進(jìn)行區(qū)分)

一般來(lái)說(shuō),我們所涉及的拷貝對(duì)象,也都是針對(duì)引用類型的。由于引用類型屬性層級(jí)可能也會(huì)有多層,這樣也就引出了我們所要去了解的 淺拷貝深拷貝

淺拷貝

顧名思義,所謂淺拷貝就是對(duì)對(duì)象進(jìn)行淺層次的復(fù)制,只復(fù)制一層對(duì)象的屬性,并不包括對(duì)象里面的引用類型數(shù)據(jù)

想象一下,如果讓你自己去實(shí)現(xiàn)這個(gè)功能,又會(huì)有怎么的思路呢

首先,我們需要知道被拷貝對(duì)象有哪些屬性吧,然后還需要知道這些屬性都對(duì)應(yīng)了那些值或者地址的引用吧。那么,答案已經(jīng)呼之欲出了,是的,循環(huán)

var person = {
    name: "tt",
    age: 18,
    friends: ["oo", "cc", "yy"]
}

function shallowCopy(source) {
    if (!source || typeof source !== "object") {
        throw new Error("error");
    }
    var targetObj = source.constructor === Array ? [] : {};
    for (var keys in source) {
        if (source.hasOwnProperty(keys)) {
            targetObj[keys] = source[keys];
        }
    }
    return targetObj;
}

var p1 = shallowCopy(person);

console.log(p1)

在上面的代碼中,我們創(chuàng)建了一個(gè) shallowCopy 函數(shù),它接收一個(gè)參數(shù)也就是被拷貝的對(duì)象。

首先創(chuàng)建了一個(gè)對(duì)象
然后 for...in 循環(huán)傳進(jìn)去的對(duì)象,為了避免循環(huán)到原型上面會(huì)被遍歷到的屬性,使用 hasOwnProperty 限制循環(huán)只在對(duì)象自身,將被拷貝對(duì)象的每一個(gè)屬性和值添加到創(chuàng)建的對(duì)象當(dāng)中
最后返回這個(gè)對(duì)象
通過(guò)測(cè)試,我們拿到了和 person 對(duì)象幾乎一致的對(duì)象 p1。看到這里,你是不是會(huì)想那這個(gè)結(jié)果和 var p1 = person 這樣的賦值操作又有什么區(qū)別呢?

我們?cè)賮?lái)測(cè)試一波

var p2 = person;

// 這個(gè)時(shí)候我們修改person對(duì)象的數(shù)據(jù)
person.name = "tadpole";
person.age = 19; 
person.friends.push("tt")

p2.name // tadpole
p2.age // 19
p2.friends // ["oo", "cc", "yy", "tt"]

p1.name // tt
p1.age // 18
p1.friends // ["oo", "cc", "yy", "tt"]

上面我們創(chuàng)建了一個(gè)新的變量 p2 ,將 person 賦值給 p2 ,然后比較兩個(gè)變量

深拷貝
了解完淺拷貝,相信小伙伴們對(duì)于深拷貝也應(yīng)該了然于胸了

淺拷貝由于只是復(fù)制一層對(duì)象的屬性,當(dāng)遇到有子對(duì)象的情況時(shí),子對(duì)象就會(huì)互相影響。所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝

實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝

function deepCopy(source){
   if(!source || typeof source !== "object"){
     throw new Error("error");
   }
   var targetObj = source.constructor === Array ? [] : {};
   for(var keys in source){
      if(source.hasOwnProperty(keys)){
         if(source[keys] && typeof source[keys] === "object"){
           targetObj[keys] = source[keys].constructor === Array ? [] : {};
           targetObj[keys] = deepCopy(source[keys]);
         }else{
           targetObj[keys] = source[keys];
         }
      } 
   }
   return targetObj;
}
var obj1 = {
    arr: [1, 2, 3],
    key: {
        id: 22
    },
    func: function() {
        console.log(123)
    }
}

var obj2 = deepCopy(obj1);

obj1.arr.push(4);

obj1.arr // [1, 2, 3, 4]
obj2.arr // [1, 2, 3]
obj1.key === obj2.key // false
obj1.func === obj2.func // true

對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。只是在拷貝的過(guò)程中源對(duì)象的方法丟失了,這是因?yàn)樵谛蛄谢?JavaScript 對(duì)象時(shí),所有函數(shù)和原型成員會(huì)被有意忽略

還有一種實(shí)現(xiàn)深拷貝的方式是利用 JSON 對(duì)象中的 parse 和 stringify,JOSN 對(duì)象中的 stringify 可以把一個(gè) js 對(duì)象序列化為一個(gè) JSON 字符串,parse 可以把 JSON 字符串反序列化為一個(gè) js 對(duì)象,通過(guò)這兩個(gè)方法,也可以實(shí)現(xiàn)對(duì)象的深復(fù)制

// 利用JSON序列化實(shí)現(xiàn)一個(gè)深拷貝
function deepCopy(source){
  return JSON.parse(JSON.stringify(source));
}
var o1 = {
  arr: [1, 2, 3],
  obj: {
    key: "value"
  },
  func: function(){
    return 1;
  }
};
var o2 = deepCopy(o1);
console.log(o2); // => {arr: [1,2,3], obj: {key: "value"}}

實(shí)現(xiàn)拷貝的其他方式

淺拷貝
·Array.prototype.slice()
·Array.prototype.concat()
·Object.assign
·拓展操作符...
...
深拷貝
很多框架或者庫(kù)都提供了深拷貝的方式,比如 jQuery 、 lodash 函數(shù)庫(kù)等等,基本實(shí)現(xiàn)方式也就和我們前面介紹的大同小異

后記
根據(jù)需求的不同,比如有時(shí)候我們需要一個(gè)全新的對(duì)象,在修改它的時(shí)候不去影響到源對(duì)象,那么這個(gè)時(shí)候我們就可能需要深拷貝;反之,淺拷貝就能實(shí)現(xiàn)我們的需求

只是,我們需要注意到一點(diǎn),那就是因?yàn)閷?shí)現(xiàn)深拷貝使用遞歸的方式,就增加了性能的消耗

相信在不斷使用的過(guò)程中,一定會(huì)對(duì)它越來(lái)越熟悉

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

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

相關(guān)文章

  • JavaScript的淺拷貝與深拷貝

    摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。 上一篇 JavaScript中的繼承 前言 文章開始之前,讓我們先思考一下這幾個(gè)問(wèn)題: 為什么會(huì)有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實(shí)現(xiàn)淺拷貝與深拷貝 好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處...

    AZmake 評(píng)論0 收藏0
  • 關(guān)于js的淺拷貝與深拷貝

    摘要:原文地址淺拷貝和深拷貝只針對(duì)像這樣的復(fù)雜對(duì)象的簡(jiǎn)單來(lái)說(shuō),淺拷貝只拷貝一層對(duì)象的屬性,而深拷貝則遞歸拷貝了所有層級(jí)。淺拷貝通過(guò)來(lái)實(shí)現(xiàn)淺拷貝。 原文地址:http://www.silenceboy.com/201... 淺拷貝和深拷貝只針對(duì)像Object, Array這樣的復(fù)雜對(duì)象的.簡(jiǎn)單來(lái)說(shuō),淺拷貝只拷貝一層對(duì)象的屬性,而深拷貝則遞歸拷貝了所有層級(jí)。 淺拷貝 通過(guò) Object.ass...

    summerpxy 評(píng)論0 收藏0
  • 淺談JavaScript的淺拷貝與深拷貝

    摘要:引用數(shù)據(jù)類型是存放在堆內(nèi)存中的,變量實(shí)際上是一個(gè)存放在棧內(nèi)存的指針,這個(gè)指針指向堆內(nèi)存中的地址。棧和堆的區(qū)別其實(shí)淺拷貝和深拷貝的主要區(qū)別就是數(shù)據(jù)在內(nèi)存中的存儲(chǔ)類型不同。這里,對(duì)存在子對(duì)象的對(duì)象進(jìn)行拷貝的時(shí)候,就是深拷貝了。 數(shù)據(jù)類型 在開始拷貝之前,我們從JavaScript的數(shù)據(jù)類型和內(nèi)存存放地址講起。數(shù)據(jù)類型分為基本數(shù)據(jù)類型 和引用數(shù)據(jù)類型 基本數(shù)據(jù)類型主要包括undefin...

    娣辯孩 評(píng)論0 收藏0
  • 關(guān)于JavaScript的淺拷貝和深拷貝

    摘要:引用類型值引用類型值是保存在堆內(nèi)存中的對(duì)象,變量保存的只是指向該內(nèi)存的地址,在復(fù)制引用類型值的時(shí)候,其實(shí)只復(fù)制了指向該內(nèi)存的地址。 前言 要理解 JavaScript中淺拷貝和深拷貝的區(qū)別,首先要明白JavaScript的數(shù)據(jù)類型。JavaScript有兩種數(shù)據(jù)類型,基礎(chǔ)數(shù)據(jù)類型和引用數(shù)據(jù)類型。js的基本類型:undefined,null,string,boolean,number,s...

    shenhualong 評(píng)論0 收藏0
  • JS引用類型數(shù)據(jù)的淺拷貝與深拷貝

    摘要:拷貝到,屬性均順利拷貝。大輝小輝,小輝,大輝小輝,小輝,大輝但是,若修改的屬性變?yōu)閷?duì)象或數(shù)組時(shí),那么對(duì)象之間就會(huì)發(fā)生關(guān)聯(lián)。深拷貝不希望對(duì)象之間產(chǎn)生關(guān)聯(lián),那么這時(shí)候可以用到深拷貝。 淺拷貝 之前文章提到,在定義一個(gè)對(duì)象或數(shù)組時(shí),變量存放的往往只是一個(gè)地址。當(dāng)我們對(duì)堆內(nèi)存中的對(duì)象復(fù)制時(shí),如果屬性是對(duì)象或數(shù)組時(shí),這時(shí)候我們拷貝的只是一個(gè)棧內(nèi)存的指針。因此b對(duì)象在訪問(wèn)該屬性時(shí),會(huì)根據(jù)指針尋找...

    MangoGoing 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<