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). 原型不屬性參與合並
情況二:
例: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----對象的合並與克隆與數組的深淺克隆