landing_image landing_image landing_image landing_image landing_image landing_image landing_image
portrait

YX.S

成為一個厲害的普通人

post-image

之前在寫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 可以用

不過我就沒有研究了