目標
介紹 JavaScript 賦值時何時為複製(Copy)以及引用(refrence)。
step 1 : 原始型別(Call by value)
原始型別(String、Number、Boolean、Null、undefined、NaN),複製時為 Call by value
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
step 2 : 物件型別(Call by refrence)-陣列複製
物件型別(object、array)複製時為 Call by reference
// Let's say we have an array
const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
// and we want to make a copy of it.
const team = players; // team 與 palyers 指向同個記憶體位置(陣列['Wes', 'Sarah', 'Ryan', 'Poppy']),
console.log(players, team);
// team[3] 由於與 palyers 指向同個記憶體位置,所以 team[3] ="Lux" 時,players[3] 也同樣改變
team[3] = 'Lux'; // ["Wes", "Sarah", "Ryan", "Lux"] ["Wes", "Sarah", "Ryan", "Lux"]
// 複製時爲了避免因爲因 call by reference 改變到原有的陣列,有以下幾種複製方法
// slice will return a new array
const team2 = players.slice();
// or create a new array and concat the old one in
const team3 = [].concat(players);
// or use the new ES6 Spread
const team4 = [...players];
team4[3] = 'heeee hawww';
console.log(team4);
// or use Array.from()
const team5 = Array.from(players);
step 3 : 物件型別(Call by refrence)- 物件複製
// with Objects
const person = {
name: 'Wes Bos',
age: 80
};
// and think we make a copy:
const captain = person;
captain.number = 99; // person = { name: 'Wes Bos',age: 99};
const cap2 = Object.assign({}, person, { number: 99, age: 12 });
console.log(cap2); // Object {name: "Wes Bos", age: 12, number: 99}
// We will hopefully soon see the object ...spread
const cap3 = {...person};
// Things to note - this is only 1 level deep - both for Arrays and Objects. lodash has a cloneDeep method, but you should think twice before using it.
const wes = {
name: 'Wes',
age: 100,
social: {
twitter: '@wesbos',
facebook: 'wesbos.developer'
}
};
console.clear();
console.log(wes);
const dev = Object.assign({}, wes);
dev.age = 50;
dev.social.twitter = '@asdf111';
console.log('wes', wes);
console.log('dev', dev); // wes 的 social 下的 twitter 的值為'@asdf111'
step 4 : JSON.parse(JSON.stringify())
當物件型別要複製到第二層時,先將陣列或物件變成 string 後在轉成 JSON 格式(需排除第二層有 function )
const dev2 = JSON.parse(JSON.stringify(wes));
參考資料:
- JavaScript Fundamentals: Reference VS Copy #JavaScript30 14/30 @Wes Bos
- [ Alex 宅幹嘛 ] 👨💻 深入淺出 Javascript30 快速導覽 | Day 14:JavaScript References @Alex 宅幹嘛
- 14 - JavaScript References VS Copying @guahsu
- 14 JS中的引用与复制@soyaine
- Javascript Reference VS copy@dustin
- [JS30 自學筆記 Day14_Object and Arrays - Reference VS Copy](https://ithelp.ithome.com.tw/articles/10300497@jen147774ny
- JS30-Day14-JS Reference VS Copy@王郁翔
- 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?@Huli