案例
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 } }