[JS30] Day14: Object and Arrays - Reference VS Copy
這堂課是在介紹複製一個 Array 或是 Object 時,是複製到了他的參照位址還是實際值,英文常這樣說 by reference or by value.
JavaScript
start with strings, numbers and booleans. 三者都是 pass by value
let name = "steven";
let name2 = name;
console.log(name, name2); // steven steven
name2 = "thibe";
console.log(name, name2); // steven thibe
let number = 1;
number2 = number;
console.log(number, number2); // 1 1
number2 = 2;
console.log(number, number2); // 1 2
let booleans = true;
let booleans2 = booleans;
console.log(booleans, booleans2); // true true
booleans2 = false;
console.log(booleans, booleans2); // true false
當在 Array 和 Objects 時,這樣的賦值是 pass by reference,一邊做改變時,會影響到另一邊,因為他們都儲存相同的位址
const players = ["Wes", "Sarah", "Ryan", "Poppy"];
const players2 = players;
players2[0] = "Steve";
console.log(players, players2);
// ['Steve', 'Sarah', 'Ryan', 'Poppy'] ['Steve', 'Sarah', 'Ryan', 'Poppy']
const person = {
name: "Wes Bos",
age: 80,
};
const person2 = person;
person.name = "Steven";
console.log(person, person2);
// ['Steve', 'Sarah', 'Ryan', 'Poppy'] ['Steve', 'Sarah', 'Ryan', 'Poppy']
Array
Array 有四種常見方法可以複製到值
- slice
// one way
const team = players.slice();
- concat
// or create a new array and concat the old one in
const team2 = [].concat(players);
- es6 ...operator
// or use the new ES6 Spread
const team3 = [...players];
- Array.from
// now when we update it, the original one isn't changed
const team4 = Array.from(players);
但要注意的是,這邊可以複製到值僅限於一維陣列,若是二維陣列的話,第二維還是只能複製到參照位址
const nameArray = [
["Steven", "Thibe"],
["Tim", "Jimmy"],
];
const nameArray2 = [...nameArray];
nameArray2[0][0] = "Thibe";
console.log(nameArray, nameArray2);
Object
Object 有兩種常見方法可以複製到值
const person = {
name: "Wes Bos",
age: 80,
};
- assign
const cp = Object.assign({}, person, { number: 99 });
console.log(person, cp);
// {name: 'Steven', age: 80} {name: 'Steven', age: 80, number: 99}
- es6 ...operator
const cp2 = { ...person };
console.log(cp2);
cp2.age = 25;
console.log(person, cp, cp2);
// {name: 'Steven', age: 80} {name: 'Steven', age: 80, number: 99} {name: 'Steven', age: 25}
而上面的方法也會遇到跟 Array 一樣的問題,就是只會複製第一層的值,如果真的必須深層複製,就需要透過一些Deep Clone的方法。
Deep Clone
最常見的 Deep Clone 方法是轉成 Json 再轉回 JavaScript
const obj2 = JSON.parse(JSON.stringify(obj));
但實際上 deep clone 和 JSON 方法還是有著差異,可以參考以下文章,故回到 Wes Bos 所說的在我們使用深拷貝時,要先思考是否真的需要,需要的話再去尋找方法如何 deep clone。
deep clone: https://dev.to/samanthaming/how-to-deep-clone-an-array-in-javascript-3cig