深拷贝与浅拷贝
原始值直接存储在栈中;而引用值真实的数据存储在堆内存中,栈内存中存储的只是指向堆内存的引用地址。
浅拷贝是直接拷贝栈数据,原始值拷贝值,引用值拷贝的是指向堆的地址。修改引用值可能会造成所有指向这个地址的对象都会被改变。深拷贝对于原始值也是直接拷贝栈数据,但对于引用值则是重新在堆中开辟空间存放引用值,栈中地址指向堆中新开辟的空间,与被拷贝的引用值栈中地址指向不同,所以互不干扰。
深拷贝
- 方案一:利用递归依次遍历引用值,直到找到原始值。
let obj = {
name: "peter",
sex: "male",
age: 18,
tel: "18642022222",
hobbit: ['football', 'music', 'moive'],
mood: null,
family: {
'father': {
name: 'lilei',
age: 50
},
'mother': {
name: 'hanmeimei',
age: 45
}
}
}
function deepClone(target, origin){
target = target || {};
for (const key in origin) {
if (origin.hasOwnProperty(key)) {
// 空 || 原始值
if(origin[key] === null || typeof origin[key] !== 'object'){
target[key] = origin[key];
}
// 引用值
else{
// 判断当前数据是数组还是对象
target[key] = Object.prototype.toString.call(origin[key]) === '[object Array]' ? [] : {};
// 递归赋值,直到数据变成了原始值
deepClone(target[key], origin[key]);
}
}
}
return target;
}
let newObj = {}
let res = deepClone(newObj, obj);
console.log(res); // {name: 'peter', sex: 'male', age: 18, tel: '18642022222', hobbit: Array(3), …}
res.family.father.age = 80;
console.log(obj.family.father.age); // 50 原数据未受影响
- 方案二:利用JSON自带函数。
var obj = {
name: 'peter',
age: 18,
money: undefined,
mood: null,
hobbit: ['ball', 'music', 'moive']
}
var targetObj = JSON.parse(JSON.stringify(obj));
console.log(targetObj); // {name: 'peter', age: 18, mood: null, hobbit: Array(3)}
obj.hobbit[0] = 'read';
console.log(targetObj.hobbit); // ["ball", "music", "moive"]
console.log(obj.hobbit); // ["read", "music", "moive"]
弊端是
undefined数据无法拷贝。
浅拷贝
- 方案一:利用 Object.assign(target, origin)。
var obj = {
name: 'peter',
age: 18,
hobbit: ['ball', 'music', 'moive']
}
var targetObj = {};
Object.assign(targetObj, obj);
obj.hobbit[0] = 'read'; // 相应的 obj1.hobbit也会被修改
console.log(targetObj.hobbit[0]); // 'read'
- 方案二:for in 循环。
var obj = {
name: '张三',
age: 20,
sex: 'male',
family: {
father: '李四',
mother: '王五'
}
}
function clone(origin, target) {
target = target || {};
for (var k in origin) {
if (origin.hasOwnProperty(k)) {
target[k] = origin[k];
}
}
return target;
}
var targetObj = clone(obj);
console.log(targetObj); // {name: "张三", age: 20, sex: "male", family: {father: "李四", mother: "王五"}}