案例
let obj = { // 對象
name: 'father',
person: {
name: 'son',
age: 18
}
}
function change(param) {
param.person.name = 'didi'
}
console.log(obj) // { name: 'father', person: { name: 'son', age: 18 } }
change(obj)
console.log(obj) // { name: 'father', person: { name: 'didi', age: 18 } }
上面的案例中只是把obj當參數傳遞給change方法,但是發覺在change方法裏面的參數param改變了person的屬性,obj對象裏面的person屬性也會相應的改變。可以得出即使obj作爲參數,被方法調用,也會改變對象裏面的數值。
解決方案
裏面的原理和對象的地址指向問題有關,這裏證明了即使是作爲參數,他們指向的堆的地址也是一致的。因爲可以使用改變堆地址的方式解決
- 方案一深拷貝:
let obj = { // 對象
name: 'father',
person: {
name: 'son',
age: 18
}
}
function change(param) {
let obj1 = {}; // 空對象
deepCopy(param, obj1) // 深拷貝
console.log(obj1) // { name: 'father', person: { name: 'son', age: 18 } }
obj1.person.name = 'didi'
console.log(obj1) // { name: 'father', person: { name: 'didi', age: 18 } }
}
function deepCopy(o1, o2) {
for (var key in o1) {
// 獲取key屬性對應的值
var item = o1[key];
// 如果item 是對象?
// var o = {}
if (item instanceof Object) {
// var o = {};
o2[key] = {};
deepCopy(item, o2[key]);
} else if (item instanceof Array) {
// 如果item 是數組呢?
// var arr = [];
o2[key] = [];
deepCopy(item, o2[key]);
} else {
// 如果是簡單類型
o2[key] = o1[key];
}
}
}
console.log(obj) // { name: 'father', person: { name: 'son', age: 18 } }
change(obj)
console.log(obj) // { name: 'father', person: { name: 'son', age: 18 } }
- 方案二 JSON.parse(JSON.stringify())
let obj = { // 對象
name: 'father',
person: {
name: 'son',
age: 18
}
}
function change(param) {
let obj1 = JSON.parse(JSON.stringify(param)); // JSON對象轉換
console.log(obj1) // { name: 'father', person: { name: 'son', age: 18 } }
obj1.person.name = 'didi'
console.log(obj1) // { name: 'father', person: { name: 'didi', age: 18 } }
}
console.log(obj) // { name: 'father', person: { name: 'son', age: 18 } }
change(obj)
console.log(obj) // { name: 'father', person: { name: 'son', age: 18 } }