欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript簡單實現深淺拷貝過程詳解

 更新時間:2019年10月08日 09:52:36   作者:有夢想的咸魚前端  
這篇文章主要介紹了javascript簡單實現深淺拷貝過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

前言

深淺拷貝知識在我們的日常開發(fā)中還算是用的比較多,但是之前的狀態(tài)一直都是只曾聽聞,未曾使用(其實用了只是自己沒有意識到),所以今天來跟大家聊一聊js的深淺拷貝;

首先我們來了解一下javascript的數據類型,在ES5版本的js中我們的javascript一共有6種數據類型,分別是:

Number(數值型)、String(字符串)、Boolean(布爾型)、Object(對象,object和array都屬于Object類型)、null、undefined

我們日常使用的javascript深淺拷貝主要是面向Object引用類型進行拷貝; 

我們知道了js的深淺拷貝面對的執(zhí)行操作對象,然后我們再來看一下深淺拷貝的概念:

拷貝顧名思義就是復制,內存中一共分為棧內存和堆內存兩大區(qū)域,所謂深淺拷貝主要是對javascript引用類型數據進行拷貝一份,淺拷貝就是引用類型數據相互賦值之后,例obj1=obj2;如果后面的操作中修改obj1或者obj2,這個時候數據是會進行相應的變化的,因為在內存中引用類型數據是存儲在堆內存中,堆內存中存放的是引用類型的值,同時會有一個指針地址指向棧內存,兩個引用類型數據地址一樣,如果其中一個發(fā)生變化另外一個都會有影響;而深拷貝則不會,深拷貝是會在堆內存中重新開辟一塊空間進行存放;

基本類型復制:

var a = 1;
var b = a;//復制
console.log(b)//1
a = 2;//改變a的值
console.log(b)//1
console.log(a) //2

因為a,b都是屬于基本類型,基本類型的復制是不會影響對方的,因為基本類型是每一次創(chuàng)建變量都會在棧內存中開辟一塊內存,用來存放值,所以基本類型進行復制是不會對另外一個變量有影響的;

引用類型復制:

引用類型的復制我們分為數組的復制和對象的復制兩個方面來進行講解:

js的淺拷貝:

var arr1 = ['red','green'];
var arr2 = arr1;//復制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改變color1的值
console.log(arr2)//['red','green','black']
console.log(arr1) //["red", "green", "black"]

上面的案例是javascript數組的淺拷貝,通過上面的知識我們可以看知道數組是引用類型數據,引用類型數據復制是會進行相互影響的,我們看到arr1.push('black')添加了一個新的子項,因為上面var arr2=arr1這行代碼是將兩個引用類型數據的地址指針指向了同一塊堆內存區(qū)域,所以不管是arr1還是arr2修改,任何一個一個改動兩個數組都是會互相產生影響的;上面的那種直接賦值方式的復制就是我們常說的引用類型的淺拷貝;

關于深拷貝很多同學都誤以為js的原生方法concat、slice是屬于深拷貝,其實不是的;js的原生方法concat、slice都是僅適用于一維數組,一旦到了二維數組或者多維數組中就會出現問題,就出現拷貝的不夠徹底導致還是會發(fā)生數據的相互牽引問題;

slice:

var arr1 = ['red','green'];
var arr2 = arr1.slice(0);//復制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改變color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]

js原生的方法slice會返回一個新的數組,上述代碼乍一看會以為是深拷貝,因為arr2和arr1相互復制和牽引,而當arr1調用了push方法添加了新數組子項的時候,arr2沒有發(fā)生變化;是的,這是符合深拷貝的特性,但是拷貝的不夠徹底,所以還不能算是真正意義上的深拷貝,所以slice只能被稱為淺拷貝;slice方法只適用于一維數組的拷貝,在二維數組中就會破綻百出;

下面我們再來看一下二維數組的例子:

var arr1=[1,2,3,['1','2','3']];
var arr2=arr1.slice(0);
 arr1[3][0]=0;
 console.log(arr1);//[1,2,3,['0','2','3']]
 console.log(arr2);//[1,2,3,['0','2','3']]

上述代碼是一個二維數組,當我們在arr1[3][0]里面進行更改arr1的值的時候,我們發(fā)現arr1、arr2兩個數組的值都發(fā)生了變化;所以事實證明slice不是深拷貝;

concat:

var arr1 = ['red','green'];
var arr2 = arr1.concat();//復制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改變color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]
var arr1=[1,2,3,['1','2','3']];
var arr2=arr1.concat();
 arr1[3][0]=0;
 console.log(arr1);//[1,2,3,['0','2','3']]
 console.log(arr2);//[1,2,3,['0','2','3']]

concat方法在一維數組中是不會影響源數組的數據的,而在二維數組中concat的表現和slice是一樣的;

js的深拷貝:

js數組中實現深拷貝的方法都多種,比如JSON.parse(JSON.stringify())和遞歸以及JQuery庫的extend方法(只是extend方法需要依賴JQuery庫,所以我們盡量的使用原生的方式來實現)都是可以實現數組和對象的深拷貝的;

var arr1 = ['red','green'];
var arr2 = JSON.parse(JSON.stringify(arr1));//復制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改變color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]

上述代碼中我們可以清晰的看到JSON.parse(JSON.stringify())是真正意義上實現了深拷貝;

遞歸實現深拷貝:

function deepClone(obj){
  //判斷參數是不是一個對象
  let objClone = obj instanceof Object?[]:{};
  if(obj && typeof obj==="object"){
    for(key in obj){
      if(obj.hasOwnProperty(key)){
        //判斷ojb子元素是否為對象,如果是,遞歸復制
        if(obj[key]&&typeof obj[key] ==="object"){
          objClone[key] = deepClone(obj[key]);
        }else{
          //如果不是,簡單復制
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}  

var a ={
  x:1,
  y:2
};
b=deepClone(a);
a.x=3
console.log(a);
console.log(b);

輸出效果如下:

總結:

1:深拷貝只是從源數據中拷貝一份出來進行操作,而不是改變源數據;改變源數據的那是淺拷貝;

2:原生js方法slice、concat都不是真正意義上的深拷貝,都僅只適用于一維數組,拷貝的屬性不夠徹底;

3:實現js深拷貝我們可以通過JSON.parse(JSON.stringify())、遞歸以及JQuery庫的extend方法來實現;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Javascript之this關鍵字深入解析

    Javascript之this關鍵字深入解析

    如我之前的文章所述(Javascript作用域),定義在全局的函數,函數的所有者就是當前頁面,也就是window對象
    2013-11-11
  • 用js實現放大鏡的效果的簡單實例

    用js實現放大鏡的效果的簡單實例

    下面小編就為大家?guī)硪黄胘s實現放大鏡的效果的簡單實例。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • js超時調用setTimeout和間歇調用setInterval實例分析

    js超時調用setTimeout和間歇調用setInterval實例分析

    這篇文章主要介紹了js超時調用setTimeout和間歇調用setInterval,以實例形式對比分析了setTimeout與setInterval的具體使用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-01-01
  • 使用JavaScript實現一個拖拽縮放效果

    使用JavaScript實現一個拖拽縮放效果

    這篇文章主要介紹了如何使用JS實現一個這樣的拖拽縮放效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • layui中的tab控件點擊切換觸發(fā)事件

    layui中的tab控件點擊切換觸發(fā)事件

    這篇文章主要介紹了layui中的tab控件點擊切換觸發(fā)事件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 點擊按鈕或鏈接不跳轉只刷新頁面的腳本整理

    點擊按鈕或鏈接不跳轉只刷新頁面的腳本整理

    點擊按鈕或鏈接時不跳轉只刷新頁面,在某些情況下還是比較實用的,下面整理些不錯的示例,感興趣的朋友可以參考下
    2013-10-10
  • Javascript實現禁止輸入中文或英文的例子

    Javascript實現禁止輸入中文或英文的例子

    這篇文章主要介紹了Javascript實現禁止輸入中文或英文的方法實例,本文方法都是使用正則表達式實現,需要的朋友可以參考下
    2014-12-12
  • javascript實現抽獎程序的簡單實例

    javascript實現抽獎程序的簡單實例

    下面小編就為大家?guī)硪黄猨avascript實現抽獎程序的簡單實例。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • 原生js實現簡易抽獎系統(tǒng)

    原生js實現簡易抽獎系統(tǒng)

    這篇文章主要為大家詳細介紹了原生js實現簡易抽獎系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 微信小程序form表單組件示例代碼

    微信小程序form表單組件示例代碼

    這篇文章主要介紹了微信小程序form表單組件示例代碼,文章給大家提到了一些相關屬性名和類型及說明,需要的朋友可以參考下
    2018-07-07

最新評論