用擴充套件運算子進行深拷貝的注意事項
阿新 • • 發佈:2018-11-04
陣列和物件的拷貝方式有很多,此處只針對擴充套件運算子...對陣列和物件的深拷貝方式進行說明。
用擴充套件運算子深拷貝陣列:
直接貼上程式碼:
let arr = [1, 2, 3, 4, 5, 6];
let arr1 = [...arr];
arr1.push(7);
console.log(arr); //[1, 2, 3, 4, 5, 6]
console.log(arr1); //[1, 2, 3, 4, 5, 6, 7]
當陣列是一維陣列時,擴充套件運算子可以進行完全深拷貝,改變拷貝後陣列的值並不會影響拷貝源的值。
但是,當陣列為多維時:
let arr = [1, 2, 3, 4, 5, 6, [1, 2, 3]]; let arr1 = [...arr]; arr1.push(7); arr1[arr1.length - 2][0] = 100; console.log(arr); //[1, 2, 3, 4, 5, 6,[100, 2, 3]] console.log(arr1); //[1, 2, 3, 4, 5, 6, [100, 2, 3],7]
由上可見,我們不難發現當改變拷貝後陣列中第二層陣列的值時,arr1arr1.length - 2 = 100;拷貝前陣列第二層陣列的值也跟著改變了。
物件同理:
當物件只有一層時:
let obj = { name: "Wawa", age: 13, gender: "female" }; let obj1 = {...obj }; obj1.height = 165; console.log(obj);//{name: "Wawa", age: 13, gender: "female"} console.log(obj1);//{name: "Wawa", age: 13, gender: "female", height: 165}
可以用擴充套件運算子進行完全深拷貝。
但當物件有多層時:
let obj = { name: "Wawa", age: 13, gender: "female", hobby: { a: 'Chinese', b: 'Math', c: 'English' } }; let obj1 = {...obj }; obj1.hobby.a = "PE"; console.log(obj); //{name: "Wawa", age: 13, gender: "female",hobby:{a: "PE", b: "Math", c: "English"}} console.log(obj1); //{name: "Wawa", age: 13, gender: "female", ,hobby:{a: "PE", b: "Math", c: "English"},height: 165}
擴充套件運算子並不能打散第二層物件的值,且無法對其進行深拷貝,拷貝前和拷貝後第二層物件的引用地址仍然是同一個,一方改變,另一方也改變。
結論:用擴充套件運算子對陣列或者物件進行拷貝時,只能擴充套件和深拷貝第一層的值,對於第二層極其以後的值,擴充套件運算子將不能對其進行打散擴充套件,也不能對其進行深拷貝,即拷貝後和拷貝前第二層中的物件或者陣列仍然引用的是同一個地址,其中一方改變,另一方也跟著改變。
另外有一個疑問,官方說用Object.assign()拷貝時是淺拷貝,可無論我怎麼操作都是深拷貝的效果,望大家指出理解錯誤的地方,此處貼上測試的demo:
let obj3 = {
name: "Gucci",
age: 13,
gender: "female",
hobby: {
a: 'Chinese',
b: 'Math',
c: 'English'
}
};
let obj4 = Object.assign({}, obj3);
obj4.hobby.a = "Math";
obj3.age = 1000;
console.log(obj3);
console.log(obj4.age);
無論是一層還是二層,改變拷貝之後屬性的值,拷貝前物件中的任何值並沒有發生改變,且互不影響,這不是深拷貝嗎???