1. 程式人生 > >JS----對象的合並與克隆與數組的深淺克隆

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

net for循環 truct 自身 ext src 循環 高級 淺克隆

在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). 原型不屬性參與合並

情況二:

例: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)

運行結果如下:

技術分享圖片

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