Happylab Logo
發布於

Day14: JS Reference VS Copy

Authors

簡介: JavaScript 中 Reference 引用與 Copy 複製的差異,瞭解多種複製陣列和物件的方法。

基本資料型別的複製

let age = 100
let age2 = age
console.log(age, age2) // 100, 100
age = 200
console.log(age, age2) // 200, 100

let name = 'Wes'
let name2 = name
console.log(name, name2) // Wes, Wes
name = 'wesley'
console.log(name, name2) // wesley, Wes

陣列的引用與複製

const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']

// 直接賦值給新變數是引用(reference),兩者指向同一個陣列。
const team = players
console.log(players, team) // ['Wes', 'Sarah', 'Ryan', 'Poppy'], ['Wes', 'Sarah', 'Ryan', 'Poppy']

// 修改 team 會影響 players
team[3] = 'Lux'
console.log(players, team) // ['Wes', 'Sarah', 'Ryan', 'Lux'], ['Wes', 'Sarah', 'Ryan', 'Lux']

// 使用 slice() 方法複製陣列
const team2 = players.slice()

// 使用 concat() 方法複製陣列
const team3 = [].concat(players)

// 使用 ES6 的展開運算子(spread operator)複製陣列
const team4 = [...players]
team4[3] = 'heeee hawww'
console.log(team4) // ['Wes', 'Sarah', 'Ryan', 'heeee hawww']

// 使用 Array.from() 方法複製陣列
const team5 = Array.from(players)

物件的引用與複製

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

// 直接賦值給新變數是引用(reference),兩者指向同一個物件
const captain = person
captain.number = 99
console.log(person, captain) // { name: 'Wes Bos', age: 80, number: 99 }, { name: 'Wes Bos', age: 80, number: 99 }

// 使用 Object.assign() 方法複製物件
const cap2 = Object.assign({}, person, { number: 99, age: 12 })
console.log(cap2) // { name: 'Wes Bos', age: 12, number: 99 }

// 使用 JSON 的序列化與反序列化方法深層複製物件
const wes = {
  name: 'Wes',
  age: 100,
  social: {
    twitter: '@wesbos',
    facebook: 'wesbos.developer',
  },
}

console.clear()
console.log(wes)

const dev = Object.assign({}, wes)
const dev2 = JSON.parse(JSON.stringify(wes))

Note

  • 使用 Object.assign() 和展開運算子(spread operator)進行的複製都是淺層複製(shallow copy),僅複製第一層。如果物件中包含巢狀物件,內部的巢狀物件仍然是引用。
  • 深層複製(deep copy)可以使用 JSON.parse(JSON.stringify(obj)) 或第三方函式庫如 lodash 的 cloneDeep 方法,但需謹慎使用。