擴展運算符的應用spread打散數組[...]
(1)復制數組
數組是復合的數據類型,直接復制的話,只是復制了指向底層數據結構的指針,而不是克隆一個全新的數組。
const a1 = [1, 2]; const a2 = a1; a2[0] = 2; a1 // [2, 2]
上面代碼中,a2
並不是a1
的克隆,而是指向同一份數據的另一個指針。修改a2
,會直接導致a1
的變化。
ES5 只能用變通方法來復制數組。
const a1 = [1, 2]; const a2 = a1.concat(); a2[0] = 2; a1 // [1, 2]
上面代碼中,a1
會返回原數組的克隆,再修改a2
就不會對a1
產生影響。
擴展運算符提供了復制數組的簡便寫法。
const a1 = [1, 2]; // 寫法一 const a2 = [...a1]; // 寫法二 const [...a2] = a1;
上面的兩種寫法,a2
都是a1
的克隆。
對象及json數組的拷貝,Object.assign() {...obj} JSON.Parse 等幾種拷貝的區別
let obj = { age: 10 } let obj1 = { grade: 1, name: { first: 'bob' } } let objS = obj1 let objA = Object.assign(obj, obj1) let objJ = JSON.parse(JSON.stringify(obj1)) let objK = { ...obj1 } console.log(objA) console.log(objJ) console.log(objK) obj1.grade = 9 obj1.name.first = 'chris' console.log(objS) console.log(objA) console.log(objJ) console.log(objK)
打印結果:
{ age: 10, grade: 1, name: { first: 'bob' } }
{ grade: 1, name: { first: 'bob' } }
{ grade: 1, name: { first: 'bob' } }
{ grade: 9, name: { first: 'chris' } }
{ age: 10, grade: 1, name: { first: 'chris' } }
{ grade: 1, name: { first: 'bob' } }
{ grade: 1, name: { first: 'chris' } }
結論: 由於對象創建在堆上 棧上的變量保存其地址 所以也叫指針變量
淺拷貝 如let simpleObj = obj;
則只拷貝了 obj在棧上的指針變量給 simpleObj 也就是說simpleObj實際存儲的值是 obj的對象的內存地址 指向與 obj同樣的堆內存地址 所以改變 obj的值 simpleObj 的值也會改變
深拷貝 就是copy了一份對象 放在另一塊堆內存地址 改變之前的對象 對這個復制的對象不會有任何影響
js里有幾種深拷貝方式
Object.assign
方法實行的是淺拷貝,而不是深拷貝。也就是說,如果源對象某個屬性的值是對象,那么目標對象拷貝得到的是這個對象的引用。
... 擴展和 assign 一樣
JSON.parse(JSON.Stringify()) 深拷貝 但是缺點是不能拷貝 constructor 方法 解決辦法就是遞歸