[JS30筆記]-Day14 Object and Arrays — Reference VS Copy

Ivy Ho
IvyCodeFive
Published in
5 min readJun 11, 2022

今天要學習 JS 中「傳值」或「傳址」的觀念,以及淺層複製、深層複製的方法。

學習重點

一、字串、數字、布林 皆為傳值

二、陣列傳址

三、陣列淺層複製的 4 種方法

  1. .slice()
  2. [].concat()
  3. [… ] 展開運算符
  4. Array.from()

四、物件傳址

五、物件淺層複製的 2 種方法

  1. Object.assign({}, , )
  2. {...} 展開運算符

六、物件深層複製 — JSON.parse(JSON.stringify())

一、字串、數字、布林 皆為傳值

以上範例中,age2 只是將 age 的內容複製一份過來,此時兩者是各自獨立的,就算去改變其中一個變數的值,也不影響另一個。此種傳遞資料的概念即為「傳值」

除了以上的數字傳值範例,字串和布林也是透過「傳值」的方式,將內容複製到另一個變數,複製後就互不影響。

二、陣列傳址

players 為一個陣列,此時若讓 team = players,在 JavaScript 中是透過「引用」的方式傳遞資料,會讓兩個變數都指向同一個實體,此種傳遞資料的概念即為「傳址」

所以當我們修改 team 陣列內的其中一個項目,players 陣列也會跟著改變。

三、陣列淺層複製的 4 種方法

如果不希望修改陣列的一個項目後,會和另一個陣列互相連動,可以使用淺層複製的方式,將陣列複製成另一個新陣列。分別有以下 4 種方法 :

  1. .slice()
const team2 = players.slice();

2. [].concat()

const team2 = [].concat(players);

3. [… ] 展開運算符

const team2 = [...players];

4. Array.from()

const team2 = Array.from();

四、物件傳址

物件和陣列一樣,也是以「傳址」的方式在傳遞資料。

所以如以上範例中,用 person2 = person 複製一份的這種做法,一樣會有兩物件互相連動的問題。

五、物件淺層複製的 2種方法

  1. Object.assign({},)

複製一個物件 :

const person2 = Object.assign({}, person);

複製並改變物件內其中一個項目值 :

const person2 = Object.assign({}, person, {name: 'Wesley'});

2. {...} 展開運算符

const person2 = {...person}

以上兩種方法雖能將物件複製成另一個新物件,但當物件有第二層,修改淺層複製過後的第二層內容,依然會影響原物件

以上範例中,修改物件內 name 屬性的值,並不會影響另一個物件。但當我們修改物件內, social 物件裡的 twitter 值,另一個物件內的 twitter 值也會跟著改變。

六、物件深層複製 — JSON.parse(JSON.stringify())

如果想避免複製物件後,修改第二層的內容仍會與原物件連動,我們可以使用深層複製的方法。

但影片中有提到,不太推薦這種作法,使用前可以先思考看看是否有其必要性,因為一般很少有需要深層複製一整個物件的情況。

深層複製的方法,可以參考 lodash 函示庫內,已有的深層複製函式來幫助我們。

或是使用以下方法,先將物件用 JSON.stringify 轉為 JSON 字串,再用 JSON.parse 轉回原型別 — 物件,來做深層複製 :

const person3 = JSON.parse(JSON.stringify(person));

--

--

Ivy Ho
IvyCodeFive

"You don't have to be great to start, but you have to start to be great."