對象的擴展運算符(...)用於取出參數對象的所有可遍歷屬性,拷貝到當前對象之中。
拷貝對象
let aa = { age: 18, name: 'aaa' } let bb = {...aa}; console.log(bb); // {age: 18, name: "aaa"}
合並對象
擴展運算符(...)可以用於合並兩個對象
let aa = { age: 18, name: 'aaa' } let bb = { sex: '男' } let cc = {...aa, ...bb}; // 等同於: // let cc = Object.assign({}, aa, bb); console.log(cc); // {age: 18, name: "aaa", sex: "男"}
拷貝並修改對象
在擴展運算符后面,加上自定義的屬性,則擴展運算符內部的同名屬性會被覆蓋掉。
let aa = { age: 18, name: 'aaa' } let dd = {...aa, name: 'ddd'}; // 等同於: // let dd = {...aa, ...{name: 'ddd'}}; // let dd = Object.assign({}, aa, { name: 'ddd'}); console.log(dd); // {age: 18, name: "ddd"}
一般,在 redux 中修改 state 時,會用解構賦值的方法。
但是,解構后得到的新對象,相對於老對象,是淺拷貝,還是深拷貝?
例如,下面肯定是引用賦值:
let aa = { age: 18, name: 'aaa' } let bb = aa; bb.age = 22; console.log(aa.age); // 22
上面, 對象 bb 是 aa 的一個引用賦值。那么,如果使用解構賦值得到 bb 呢:
let aa = { age: 18, name: 'aaa' } let bb = {...aa}; bb.age = 22; console.log(aa.age); // 18
- 可見,改變 bb 的屬性 age 的值,並不會改變對象 aa 的屬性的 age 的值,所以,上面的例子bb是aa的一份拷貝
- 但是,這個拷貝是只有一層的淺拷貝,還是深拷貝?
let aa = { age: 18, name: 'aaa', address: { city: 'shanghai' } } let bb = {...aa}; bb.address.city = 'shenzhen'; console.log(aa.address.city); // shenzhen
可見,aa 解構賦值到新對象 bb,只是進行了一層淺拷貝,對象 bb 中的屬性(address)的屬性(city)還是對象 aa 中屬性的屬性的引用。
如果像拷貝 aa 中的 city 屬性,可以像下面處理:
let aa = { age: 18, name: 'aaa', address: { city: 'shanghai' } } let bb = { ...aa, address: {...aa.address} }; bb.address.city = 'shenzhen'; console.log(aa.address.city); // shanghai