JS----對象的合並與克隆與數組的深淺克隆


在js中,數組和對象的復制如果使用=號來進行復制,那只是淺拷貝。如下圖演示:

  

如上,arr的修改,會影響arr2的值,這顯然在絕大多數情況下,並不是我們所需要的結果。 
因此,數組以及對象的深拷貝就是javascript的一個基本功了。

對象:

一. 合並與克隆的差別

1. 克隆是特殊的合並(以空對象作為目標對象,非空對象作為源對象進行合並),克隆要求目標對象與源對象的 constructor相同。

2. 克隆的源對象只有一個,合並的源對象可以是多個。

二. 合並的方法

1.Object.assign():

例:var obj1 ={

      m : 1,

      n : 2,

      j : {

           r : {

              h : 2

            },

           p : 4 } ,

      p : 1

   }

       var obj2 ={ m : 2 , n : undefined, j : { h : 2 ,o:  3}}

       var obj3 = Object.assign(obj1,obj2);

結果:obj1 = { m : 2,n : undefined, j : { h : 2, o : 3 }, p : 1 };

           obj2 ={ m : 2 , n : undefined, j : { h : 2, o : 3 } };

           obj3 ={ m : 2 , n : undefined, j : { h : 2, o : 3 }, p : 1 };

注意:1).  目標對象自身也會變  obj1===obj3

           2). 此方法為淺合並

           3). undefined參與合並

           4). 原型不屬性參與合並

 

 2. $.extend:

情況一:

例:var obj1 ={ m : 1, n : 2, j : { r : { h : 2 }, p : 4 }, p : 1 }

       var obj2 ={ m : 2, n : undefined, j : { h : 2, o : 3 } }

       var obj3 = $.extend(obj1,obj2);

結果:obj1 = { m : 2, n : 2, j : { h : 2, o : 3 }, p : 1 };

           obj2 ={ m : 2, n : undefined, j : { h : 2, o : 3 } };

           obj3 ={ m : 2, n : 2, j : { h : 2, o : 3 }, p : 1 };

注意:1).  目標對象自身也會變  obj1===obj3

           2). 此方法為淺合並

           3). undefined不參與合並

           4). 原型不屬性參與合並

  • 如果目標對象與源對象有同名屬性,則后面的屬性會覆蓋前面的屬性
  • 如果只有一個參數,則直接返回該參數。即Object.assign(obj) === obj
  • 如果第一個參數不是對象,而是基本數據類型(Null、Undefined除外),則會調用對應的基本包裝類型
  • 如果第一個參數是Null和Undefined,則會報錯;如果Null和Undefined不是位於第一個參數,則會略過該參數的復制

情況二:

例:var obj1 ={ m : 1, n : 2, j : { r : { h : 2 }, p : 4 }, p : 1 }

       var obj2 ={ m : 2, n : undefined, j : { h : 2, o : 3 } }

       var obj4 = $.extend({},obj1,obj2);

結果:obj1 = { m : 1, n : 2, j : { r : { h : 2 }, p : 4 }, p : 1 };

           obj2 ={ m : 2, n : undefined, j : { h : 2, o : 3 } };

           obj3 ={ m : 2, n : 2, j : { h : 2, o : 3 }, p : 1 };

注意:1).  此方法為淺合並

           2). undefined不參與合並

           3). 原型不屬性參與合並

情況三:

例:var obj1 ={ m:1,n:2,j:{r:{h:2},p:4},p:1}

       var obj2 ={m:2,n:undefined,j:{h:2,o:3}}

       var obj3 = $.extend(true,obj1,obj2);

結果:obj1 = {m:2,n:2,j:{h:2,o:3,r:{h:2},p:4},p:1};

           obj2 ={m:2,n:undefined,j:{h:2,o:3}};

           obj3 ={m:2,n:2,j:{h:2,o:3,r:{h:2},p:4},p:1};

注意:1).  目標對象自身也會變  obj1===obj3

           2). 此方法為深合並

           3). undefined不參與合並

           4). 原型不屬性參與合並

3. 遍歷賦值法 

思路:將obj2中存在的屬性但obj1不存在的屬性賦值給obj1。

步驟:1). 遍歷obj2中屬性。

           2). 判斷obj1不存在此屬性

           3). 將次值賦給obj1

var extentObj = function(obj1,obj2){

    for(let key in obj2){

     if(obj2.hasOwnProperty(key) && (!obj1.hasOwnProperty(key))){

    obj1[key] = obj2[key]

   }

  }

}

4、擴展運算符實現對象的深拷貝

var obj = {
  name: 'FungLeo',
  sex: 'man',
  old: '18'
}
var { ...obj2 } = obj
obj.old = '22'
console.log(obj)
console.log(obj2)

  運行結果如下:

擴展運算符實現對象的深拷貝

 三. 克隆的方法

1. JSON.parse(JSON.stringify()):

    1). 先將對象變為字符串,然后再變為json對象,防止對象的指針指向問題,為深拷貝

     2). undefined 和 function 類型的屬性會被忽略,而 Date 類型的屬性則會被轉換為字符串

 2. $.extend:

    傳true為深拷貝,不傳為淺拷貝

注意:深拷貝與淺拷貝的區別

淺拷貝直接把引用地址原樣拿來,此時,不管源對象還是目標對象,修改引用屬性后另一個對象的同名屬性都會受到影響。

深拷貝則會遞歸地在目標對象上創建值,目標對象和源對象之間將完全獨立

數組:

一、 for循環實現數組的深拷貝

for循環是非常好用的。如果不知道高級方法,通過for循環能夠完成我們大多數的需求。

var arr = [1,2,3,4,5]
var arr2 = copyArr(arr)
function copyArr(arr) {
    let res = []
    for (let i = 0; i < arr.length; i++) {
     res.push(arr[i])
    }
    return res
}

如上,通過對數組的for循環,即可實現對數組的深拷貝了。

二、 slice方法實現數組的深拷貝

這個代碼實現非常簡單。原理也比較好理解,他是將原數組中抽離部分出來形成一個新數組。我們只要設置為抽離全部,即可完成數組的深拷貝。代碼如下:

var arr = [1,2,3,4,5]
var arr2 = arr.slice(0)
arr[2] = 5
console.log(arr)
console.log(arr2)

運行結果如下: 
 

三、concat 方法實現數組的深拷貝

這個代碼也非常簡單,原理更加粗暴。它是用於連接多個數組組成一個新的數組的方法。那么,我們只要連接它自己,即可完成數組的深拷貝。代碼如下:

var arr = [1,2,3,4,5]
var arr2 = arr.concat()
arr[2] = 5
console.log(arr)
console.log(arr2)

運行結果如下: 

四、ES6擴展運算符實現數組的深拷貝

OK,以上之前講的方法全部過時了,用下面的方法實現數組的深拷貝是最簡單的。

var arr = [1,2,3,4,5]
var [ ...arr2 ] = arr
arr[2] = 5
console.log(arr)
console.log(arr2)

運行結果如下:

ES6擴展運算符實現數組的深拷貝

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM