Call by Reference 還是 Call by Sharing
object 的話,基本上是 call by reference,唯一要注意的就是重新賦值這個動作造成 reference 改變的影響 → 變成 call by sharing。
物件有傳參考特性,有時會在我們想要複製物件,並且想要這個複製的物件獨立於原本的物件時會造成一些困擾 (需將兩物件完全拆離開來)… 這樣要如何解決此問題呢 ?? 以下提供幾種複製的方法,解決這個問題。
只能做第一層的複製,第二層仍舊是用傳參考的方式傳入的( call by reference)
var family = {
name: '小明家',
members: {
father: '老爸',
mom: '老媽',
ming: '小明'
},
}
var newFamily = {}; // 先新建一個物件
key 指的是物件中的第一層屬性名稱,第一層有幾個屬性、就跑幾次…
淺層複製只會複製純值,淺層複製也會宣告新的記憶體空間
內層物件只會傳參考
for (var key in family) { // 宣告一個 key,key 值包含物件的第一層屬性內容
console.log(key);
// name members ( key 值包含 family 物件第一層的屬性 )
console.log(family[key]); // 讀出屬性所對應的內容
// 小明家
// {father: "老爸", mom: "老媽", ming: "小明"}
newFamily[key] = family[key]; // 將值塞入 newFamily 之後,就完成淺拷貝
}
console.log(family, newFamily); // 兩個物件內容一樣
newFamily.name = '杰倫家'; // 只能更改第一層內容
console.log(family, newFamily); // (如下圖)
console.log(family === newFamily); // false
newFamily 和 family.members 物件其實仍指向同一個參考位置,所以 family 的 members 內容也被修改了。
newFamily.members.ming = '大明'; // 第二層還是「傳參考」模式
console.log(family, newFamily);
插入空物件,再把 family 物件傳入
var newFamily2 = jQuery.extend({}, family);
var newFamily3 = Object.assign({}, family);
var array = [];
family.forEach((item)=>{ // 淺層複製,相當於 for in 的語法
array.push(item);
})
將原本的物件轉為字串,再轉回物件,這樣傳參考的特性就消失了。
使用 JSON 方式把物件轉為字串,再轉回物件
var family = {
name: '小明家',
members: {
father: '老爸',
mom: '老媽',
ming: '小明'
},
}
console.log(family, JSON.stringify(family));
// 轉為字串,此 family 字串和原本的 family 物件已無參考關係
console.log(family, JSON.parse(JSON.stringify(family)));
// 再把 family 字串轉為物件 (和原本的 family 物件已無參考關係)
var newFamily = JSON.parse(JSON.stringify(family));
console.log(family === newFamily); // false,兩者已無關聯性
newFamily.name = '杰倫家';
newFamily.members.ming = '大明';
console.log(family, newFamily); // (如下圖) 兩者已無關聯,參考位置也不一樣
function updateEasyCard() {
let arg = [...arguments];
let sum = arg.reduce(function(accumulator, currentValue) {
return accumulator + currentValue;
}, 0);
console.log('我有 ' + sum + ' 元');
}
updateEasyCard(0); // 我有 0 元
updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); // 我有 718 元