iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
JavaScript

火箭通關JS30系列 第 14

JS30-14-JavaScript-References-VS-Copying

  • 分享至 

  • xImage
  •  

課程目的:

這次的內容是利用陣列跟物件做出深拷貝淺拷貝
作品實做

本次功能實作重點:

  • 何謂深拷貝,何謂淺拷貝
  • 陣列淺拷貝的方法
    • 擴展運算符(…)
    • Array.prototype.slice()
    • concat()
    • Array.from(players)
  • 物件淺拷貝的方法
    • Object.assign([], players)
  • 物件跟陣列深拷貝的方法
    • JSON.parse(JSON.stringify(obj))

何謂深拷貝,何謂淺拷貝

淺拷貝:
指的是只複製物件的第一層,即只複製對象的引用。

如果物件中的屬性是原始類型(如字串、數字、布林值),它們會被完整地複製,不過如果屬性是物件或陣列,淺拷貝會複製它們的記憶體位置,而不是它們的內容。這樣,如果改變這些記憶體位置的屬性,原本的引用的內容也會被改變

深拷貝:

複製物件的每一層。所有的屬性(包括嵌套的物件或陣列)都會被完整地複製,沒有共享的引用。

陣列淺拷貝的方法

 const players = ["Wes", "Sarah", "Ryan", "Poppy"];

作者一開始給我們的預設陣列,接下來就開始運用方法來拷貝陣列吧!

1.擴展運算符(…)

可用於展開陣列、物件或可迭代物件的元素,而我們可以用它淺拷貝一個陣列

let players2 = [...players]; // ["Wes", "Sarah", "Ryan", "Poppy"];

image.png

而當重新賦值players2[0] =”tema”players 則不受影響,即我們已經成功複製了他的值(淺拷貝)

2.concat()

用來合併兩個或多個陣列。此方法不會改變現有的陣列,回傳一個包含呼叫者陣列本身的值,作為代替的是回傳一個新陣列

 let players3 = [].concat(players); // ["Wes", "Sarah", "Ryan", "Poppy"];

3.Array.prototype.slice()

會回傳一個新陣列,為原陣列選擇之[0]至 end(不含 end)部分的淺拷貝(shallow copy)。而原本的陣列將不會被改變

let players4 = players.slice(); // ["Wes", "Sarah", "Ryan", "Poppy"];

4.Array.from(players)

可以將現有的陣列複製為一個新陣列,也可以將一個類似陣列的對象(如 likeArray)轉換為一個新的真正的陣列。

其實Array也有其他使用方式:例如可以將String拆解單字進一個array

 let players5 = Array.from(players); // ["Wes", "Sarah", "Ryan", "Poppy"];

物件淺拷貝的方法

 const person = {
        name: "Wes Bos",
        age: 80,
      };

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

※上面我們學到的擴展運算符(…) 也可用於淺拷貝物件資料

.Object.assign([], players)

可用來複製一個或多個物件,自己所有可數的屬性到另一個目標物件。回傳的值為該新的目標物件。

Object.assign(target, ...sources);// ["Wes", "Sarah", "Ryan", "Poppy"];

target為合併的目標

...sources 為要合併的元素

接下來來實做看看:

 let players6 = Object.assign([], players);// ["Wes", "Sarah", "Ryan", "Poppy"];

將players複製進一個空陣列,也可以達到淺拷貝的效果

物件跟陣列深拷貝的方法

JSON.parse(JSON.stringify(obj))

為物件先轉換為 JSON 字串,然後再解析回一個新的物件,從而實現深拷貝。

    const wes = {
        name: "Wes",
        age: 100,
        social: {
          twitter: "@wesbos",
          facebook: "wesbos.developer",
        },
      };
      let wes1 = { ...wes };//**注意這為淺拷貝**
      wes1["social"].twitter = "tema0105"; 
      //我們物件內的物件沒有做到深拷貝 導致我們的做這行程式碼讓wes的值一併被改變了

      let wes3 = JSON.parse(JSON.stringify(wes));

image.png

拿到控制台測試如果將wes3 屬性social.twitter改變數值,也不會改變原本wes物件內的數值,這代表我們成功做到了深拷貝

※雖然JSON.parse(JSON.stringify(obj))可以做到深拷貝,但當拷貝的內容裡有function時,無法拷貝到funtion,只會顯示其他原始類型以及物件跟陣列

最後重點整理 :

  • 淺拷貝 指的是只複製物件的第一層,即只複製對象的引用。
  • 深拷貝 複製物件的每一層。所有的屬性(包括嵌套的物件或陣列)都會被完整地複製,沒有共享的引用。
  • 擴展運算符(…) 皆可用於Obj及Array
  • JSON.parse(JSON.stringify(obj)) 可以做到深拷貝,但當拷貝的內容裡有function時,無法拷貝到funtion

導讀文件以及學習資源

[ Alex 宅幹嘛 ] 👨‍💻 深入淺出 Javascript30 快速導覽 | Day 14:JavaScript References VS Copying
JS30


上一篇
JS30-13 - Slide in on Scroll
下一篇
JS30-15 - LocalStorage
系列文
火箭通關JS3030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言