JavaScript_淺拷貝與深拷貝
JavaScript, 學習筆記
之前在寫React的時候
一直發生狀態的渲染錯誤,實在非常崩潰...
後來才想到JS有分淺拷貝與深拷貝,於是這篇就來記錄一下
JS基本型態
在JS中,資料型態基本上可以分為兩類
- Primitive(基本): String, Number, Boolean, Null, Undefined
- Composite(複合): Object, Array
然後我們想知道型態可以使用typeof()方法
唯一的例外就是Null會被顯示為Object,這是JS在上古時代發生的錯誤
淺拷貝與深拷貝
用圖來看會清楚很多
淺拷貝所複製出來的物件
會與原本的物件指向同一個位置(也就是傳址)
深拷貝才是真正的複製(傳值)
而在JS中
Primitive的型態會是深拷貝
範例:
let a = 3;
let b = a;
b = '你好';
console.log(a); // 3
console.log(b); // 你好
Composite類型則是淺拷貝
let John = { 'name':'John', 'age':18 };
let Jenny = John;
Jenny.name = 'Jenny';
console.log(John);
// { 'name':'Jenny', 'age':18 } <-- John被改名了
console.log(Jenny);
// { 'name':'Jenny', 'age':18 }
那要怎麼做才可以深拷貝呢?
1.Object.assign
Object.assign是 ES6 的新方法
被用來複製物件自身所有可數的屬性到另一個目標物件。回傳的值為該目標物件。
利用這個方法可以讓我們達成想要的結果
let John = { 'name':'John', 'age':18 };
let Jenny = Object.assign({}, John);
Jenny.name = 'Jenny';
console.log(John);
// { 'name':'John', 'age':18 } <-- John還是John
console.log(Jenny);
// { 'name':'Jenny', 'age':18 }
{}的意思是先變出一個空物件
然後在把John給填進去
所以就會得到一模一樣的物件了!
不過Object.assign只能處理深度只有一層的物件
沒辦法做到真正的深拷貝
2.轉成 JSON 再轉回來
用JSON.stringify把物件轉成字串
再用JSON.parse把字串轉成新的物件
let John = { 'name':'John', 'age':18 };
let Jenny = JSON.parse(JSON.stringify(John));
Jenny.name = 'Jenny';
console.log(John);
// { 'name':'John', 'age':18 } <-- John還是John
console.log(Jenny);
// { 'name':'Jenny', 'age':18 }
這樣做就是真正的深拷貝
但條件就是必須要可以轉乘JSON就是了
另外還有 Jquery的extend 以及 Lodash的_.cloneDeep 可以用
不過我就沒有研究了