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

資訊專欄INFORMATION COLUMN

記錄一下最近在學(xué)的深淺拷貝

cpupro / 2144人閱讀

摘要:兩者享有相同的引用。深拷貝這個(gè)問題通??梢酝ㄟ^來(lái)解決。深淺拷貝也可以使用的方法,注意使用合并返回值

前言

最近寫代碼經(jīng)常用到深淺拷貝,從一開始的悶頭使用漸漸想要深究其理,這篇文章記錄一下我的認(rèn)為,有所不足,恭請(qǐng)指正

我們可以先看看一個(gè)常遇到的一個(gè)小問題

let a = {
    age:1
}
let b = a
a.age = 2
console.log(b.age)   //2

從上面的例子中我們看到了,如果給一個(gè)變量賦值一個(gè)對(duì)象,那么兩者的值會(huì)是同一個(gè)引用,其中一方變化,另一方也會(huì)有相應(yīng)的改變。
通常我們開發(fā)中不希望出現(xiàn)這樣的問題,我們可以使用淺拷貝來(lái)解決這個(gè)問題。

淺拷貝

首先可以通過 Object.assign 來(lái)解決這個(gè)問題。

let a = {
    age:1
}
let b = Object.assign({} , a)
a.age = 2
console.log(b.age)   //1

當(dāng)然大多數(shù)情況我們比較喜歡通過展開運(yùn)算符(...)來(lái)解決

let a = {
        age:1
    }
    let b ={...a} 
    a.age = 2
    console.log(b.age)   //1

通常淺拷貝就解決了大部分問題,但是如果遇到以下情況就需要用到深拷貝了

 let a = {
            age:1,
            jobs:{
            first:"FE"
            }
        }
        let b ={...a} 
        a.jobs.first = "native"
        console.log(b.jobs.first)   //native 

淺拷貝只解決了第一層的問題,如果接下去的值還是有對(duì)象的話,那么就又回到剛剛的開始問題了。兩者享有相同的引用。要解決這個(gè)問題,我們就要引入深拷貝。

深拷貝

這個(gè)問題通??梢酝ㄟ^ JSON.parse(JSON.stringify(object)) 來(lái)解決。

 let a = {
                age:1,
                jobs:{
                first:"FE"
                }
            }
            let b =JSON.parse(JSON.stringify(a))
            a.jobs.first = "native"
            console.log(b.jobs.first)   //FE

但是該方法也是有局限性的:

會(huì)忽略u(píng)nderfind

不能序列化函數(shù)

不能解決循環(huán)引起的對(duì)象

我們?cè)倏匆幌孪旅孢@個(gè)情況

 let obj ={
 
    a:undefined,
    b:function(){},
    name:"yck"
    
   }

   let newObj = JSON.parse(JSON.stringify(obj))
   console.log(newObj) //{name : "yck"}
   

你會(huì)發(fā)現(xiàn)在上述情況中,該方法忽略掉函數(shù)和undefind
但是在通常情況下,復(fù)雜數(shù)據(jù)都是可序列化的,所以這個(gè)函數(shù)可以解決大部分問題,并且該函數(shù)是內(nèi)置函數(shù)中處理深拷貝性能最快的。當(dāng)然如果你的數(shù)據(jù)中含有以上三種情況下??梢允褂?lodash 的深拷貝函數(shù)
如果你所需要拷貝的對(duì)含有內(nèi)置類型并且不包括函數(shù),可以使用 MessageChannel

  function structuralClone(obj){
      return new Promise(resolve => {
          const {port1,port2} = new MessageChannel();
          port2.onmessage = ev =>resolve(ev.data);
          port1.postMessage(obj)
      })
  }
  var obj = {a:1,b:{
      c:b
  }}
  //注意這個(gè)方法是異步的
  //可以處理undefined和循環(huán)引用對(duì)象
  const clone = await structuralClone(obj);
  

深拷貝與淺拷貝的區(qū)別

深拷貝和淺拷貝最根本的區(qū)別在于是否是真正獲取了一個(gè)對(duì)象的復(fù)制實(shí)體,而不是引用。

淺拷貝—-只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù),拷貝后也是會(huì)發(fā)生引用,我們把這種拷貝叫做“(淺復(fù)制)淺拷貝”,換句話說(shuō),淺拷貝僅僅是指向被拷貝的內(nèi)存地址,如果原地址中對(duì)象被改變了,那么淺拷貝出來(lái)的對(duì)象也會(huì)相應(yīng)改變。

深拷貝—-在計(jì)算機(jī)中開辟了一塊新的內(nèi)存地址用于存放復(fù)制的對(duì)象。

淺拷貝實(shí)例
//此遞歸方法不包含數(shù)組對(duì)象

var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);

function shallowCopy(src) {
  var newobj = {};
  for (var prop in src) {
    if (src.hasOwnProperty(prop)) {
      newobj[prop] = src[prop];
    }
  }
  return newobj;

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

導(dǎo)致的結(jié)果就是:

shallowObj.arr[1] = 5;
console.log(obj.arr[1]);   //  5

深拷貝實(shí)例
而深復(fù)制則不同,它不僅將原對(duì)象的各個(gè)屬性逐個(gè)復(fù)制出去,而且將原對(duì)象各個(gè)屬性所包含的對(duì)象也依次采用深復(fù)制的方法遞歸復(fù)制到新對(duì)象上。這就不會(huì)存在上面 obj 和 shallowObj 的 arr 屬性指向同一個(gè)對(duì)象的問題。

var obj = { 
    a:1, 
    arr: [1,2],
    nation : "中國(guó)",
    birthplaces:["北京","上海","廣州"]
};
var obj2 = {name:"楊"};
obj2 = deepCopy(obj,obj2);
console.log(obj2);
//深復(fù)制,要想達(dá)到深復(fù)制就需要用遞歸
function deepCopy(o,c){
   var c = c || {};
   for(var i in o){
   if(typeof o[i] === "object"){
          //要考慮深復(fù)制問題了
          if(o[i].constructor === Array){
            //這是數(shù)組
            c[i] =[];
          }else{
            //這是對(duì)象
            c[i] = {};
          }
          deepCopy(o[i],c[i]);
        }else{
          c[i] = o[i];
        }
     }
     return c
 }

結(jié)果如下面的示意圖所示:

這樣obj和obj2分別擁有不同的內(nèi)存地址,兩邊值的改變互不影響。

深淺拷貝也可以使用JQuery的extend方法,注意使用合并返回值

let newObj = $.extend(true,{},partcontent);

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

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

相關(guān)文章

  • javascript之深淺拷貝

    摘要:為何寫最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內(nèi)存中,將的各個(gè)屬性都復(fù)制到新內(nèi)存里,就是深拷貝。安全的值是指能夠呈現(xiàn)為有效格式的值。參考文檔冴羽的專題之深淺拷貝深拷貝與淺拷貝的實(shí)現(xiàn) 為何寫: 最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。廢話不多說(shuō),我們來(lái)一起復(fù)習(xí)一下吧,也希望留下您寶貴意見。 何為深淺拷貝?...

    LMou 評(píng)論0 收藏0
  • JavaScript之淺、深拷貝

    摘要:前言里面淺拷貝和深拷貝是非常關(guān)鍵的知識(shí)點(diǎn),今天就來(lái)通過本文清楚的了解深淺拷貝以及該如何實(shí)現(xiàn)這兩種拷貝方式。對(duì)象的拷貝又分為淺拷貝和深拷貝。印證了上述所說(shuō)的對(duì)于所有的基本類型,簡(jiǎn)單的賦值已經(jīng)是實(shí)現(xiàn)了深拷貝。 前言 JavaScript里面淺拷貝和深拷貝是非常關(guān)鍵的知識(shí)點(diǎn),今天就來(lái)通過本文清楚的了解深淺拷貝以及該如何實(shí)現(xiàn)這兩種拷貝方式。 深淺拷貝的區(qū)別 拷貝:其實(shí)就是一個(gè)對(duì)象復(fù)制給另外...

    leanxi 評(píng)論0 收藏0
  • JS專題之深淺拷貝

    摘要:在之前的文章專題之?dāng)?shù)據(jù)類型和類型檢測(cè)中我有講過,中的數(shù)據(jù)類型分為兩種,基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型是保存在棧的數(shù)據(jù)結(jié)構(gòu)中的是按值訪問,所以不存在深淺拷貝問題。 前言 在開發(fā)過程中,偶爾會(huì)遇到這種場(chǎng)景,拿到一個(gè)數(shù)據(jù)后,你打算對(duì)它進(jìn)行處理,但是你又希望拷貝一份副本出來(lái),方便數(shù)據(jù)對(duì)比和以后恢復(fù)數(shù)據(jù)。 那么這就涉及到了 JS 中對(duì)數(shù)據(jù)的深淺拷貝問題,所謂深淺拷貝,淺拷貝的意思就是,...

    ASCH 評(píng)論0 收藏0
  • 深淺拷貝

    摘要:好像栗子不是那么好吃,那我們來(lái)看看下面的解釋吧深淺拷貝深拷貝和淺拷貝只針對(duì)像這樣的引用類型數(shù)據(jù)。深拷貝則是開啟一個(gè)新的棧,兩個(gè)對(duì)象對(duì)應(yīng)兩個(gè)不同的引用地址,修改一個(gè)對(duì)象的屬性,不會(huì)改變另一個(gè)對(duì)象的屬性。 拷貝顧名思義就是復(fù)制,但是它并不簡(jiǎn)單哦,拷貝分為深淺拷貝,那么啥是深拷貝啥是淺拷貝呢,讓我們來(lái)舉個(gè)栗子,淺拷貝就是當(dāng)你拷貝別人的U盤里東西時(shí),卻沒有新建文件存放在自己的電腦里,直接在里面...

    yck 評(píng)論0 收藏0
  • Python面試經(jīng)驗(yàn)總結(jié),面試一時(shí)爽,一直面試一直爽!

    摘要:面試的心得體會(huì)簡(jiǎn)歷制作我做了兩份簡(jiǎn)歷,用兩個(gè)手機(jī)賬號(hào),兩個(gè)簡(jiǎn)歷名字,分別在各個(gè)招聘網(wǎng)站投了雙份簡(jiǎn)歷,一個(gè)是數(shù)據(jù)分析的簡(jiǎn)歷一個(gè)是全棧開發(fā)的簡(jiǎn)歷,我真正接觸快年,不管是學(xué)習(xí)還是工作學(xué)到的東西,這兩年大概掌握了前端爬蟲數(shù)據(jù)分析機(jī)器學(xué)習(xí)技術(shù), showImg(https://upload-images.jianshu.io/upload_images/13090773-b96aac7e974c...

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

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

0條評(píng)論

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