Anthony Chao

JS30 day14 Reference vs Copy

#Javascript

JS30 day14 - Reference vs Copy

作業內容

今天主要是在釐清 JS 裡面的基本型別 pass by value 跟 pass by reference 還有怎麼應對

學到什麼

  • JS
    1. JS 裡面的數字 / 布林值 / 字串是 pass by value,但陣列跟 Object 是 pass by reference
    // 數字 字串 布林值
    let age = 100;
    let age2 = age;
    console.log(age, age2); // 100 100
    age = 200;
    console.log(age, age2);  // 200 100
    
    // 陣列
    const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
    const team = players
    console.log(players, team) // (4) ["Wes", "Sarah", "Ryan", "Poppy"] (4) ["Wes", "Sarah", "Ryan", "Poppy"]
    team[3] = 'Lux'
    console.log(players, team)  //(4) ["Wes", "Sarah", "Ryan", "Lux"] (4) ["Wes", "Sarah", "Ryan", "Lux"]
    1. 陣列的 copy 方法
    const team2 = players.slice()
    const team3 = [].concat(players)
    const team4 = [...players] //ES6
    const team5 = Array.from(players)
    1. Object 是最麻煩的,如果只有一層你可以使用 assign
    const person = {
      name: 'Wes Bos',
      age: 80
    };
    const cap2 = Object.assign({}, person, { number: 99, age: 12 })
    console.log(person, cap2)  //{name: "Wes Bos", age: 99} {name: "Wes Bos", age: 12, number: 99}
    問題是 assgin 是淺拷貝,兩層以上會出現一樣的問題 (WTF moment)
    const wes ={
      name: 'Wes',
      age: 100,
      social: {
        twitter: 'wesbos',
        facebook: 'developer'
      }
    }
    const dev = Object.assign({}, wes)
    dev.social.twitter = "qoo"
    console.log(wes, dev)
    結果如下: 他這裡有介紹一種深拷貝的方法,但效能不怎麼好:
    const dev2 = JSON.parse(JSON.stringify(wes));
    這篇文章寫得很詳細可以參考: Object深拷貝的方法

參考資料: https://github.com/wesbos/JavaScript30

code 內容:

JS:

// 對於字串 / 數字 / 布林值來說是 pass by value
let age = 100;
let age2 = age;
console.log(age, age2); // 100 100
age = 200;
console.log(age, age2);  // 200 100

// 對於陣列來說是 pass by reference
const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
const team = players
console.log(players, team) // (4) ["Wes", "Sarah", "Ryan", "Poppy"] (4) ["Wes", "Sarah", "Ryan", "Poppy"]
team[3] = 'Lux'
console.log(players, team)  //(4) ["Wes", "Sarah", "Ryan", "Lux"] (4) ["Wes", "Sarah", "Ryan", "Lux"]

// 解決方法:複製一份
const team2 = players.slice()
const team3 = [].concat(players)

// ES6 方法:打散
const team4 = [...players]
const team5 = Array.from(players)
// The same thing goes for objects, let's say we have a person object

// 對於 Object 來說也是 pass by reference
const person = {
  name: 'Wes Bos',
  age: 80
};
const captain = person
console.log(person, captain) // {name: "Wes Bos", age: 80} {name: "Wes Bos", age: 80}
captain.age = 99
console.log(person, captain) // {name: "Wes Bos", age: 99} {name: "Wes Bos", age: 99}

// 所以也要做個複製出來
const cap2 = Object.assign({}, person, { number: 99, age: 12 })
console.log(person, cap2)  //{name: "Wes Bos", age: 99} {name: "Wes Bos", age: 12, number: 99}
// 然而這個 assign 方法是 shallow 的,如果有多層結構,還是會改到原本 Object
const wes ={
  name: 'Wes',
  age: 100,
  social: {
    twitter: 'wesbos',
    facebook: 'developer'
  }
}
const dev = Object.assign({}, wes)
dev.social.twitter = "qoo"
console.log(wes, dev)
//解決方法之一:
const dev2 = JSON.parse(JSON.stringify(wes));