引入:值类型存储在栈内存中,引用类型存储在堆内存,深浅拷贝主要是针对引用类型来说的(数组、对象等)。(值类型直接赋值就能开辟新存储空间,引用类型直接赋值得到的是引用,实际还是同一个空间)
一.浅拷贝:复制的只是引用,原对象属性的改变会引起拷贝对象对应引用属性的变化。
方法1:遍历并复制(只能拷贝第一层)
function simpleCopy(obj){
const targetObj = Object.prototype.toString.call(obj) == '[object Array]'?[]:{};
for(let key in obj){
targetObj[key] = obj[key];
}
return targetObj;
}
let a = {
name:'tom',
age:20,
friends:{
student:['jack']
}
}
let b = simpleCopy(a);
a.friends.student = ['tony'];
console.log(a);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } }
console.log(b);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } }
方法2.使用Object.assign()(只能拷贝第一层)
let a = {
name:'tom',
age:20,
friends:{
student:['jack']
}
}
let b = Object.assign({},a);
a.friends.student = ['tony'];
console.log(a);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } }
console.log(b);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } }
二.深拷贝:开辟新的内存空间,原对象与拷贝对象之间没有影响。
方法1:使用JSON.parse()加JSON.stringify()
let obj = {
name:'tom',
age:10,
friend:{
name:'jack'
}
};
let copy = JSON.parse(JSON.stringify(obj));
obj.name = 'elric';
console.log(obj);// {name: "elric", age: 10, friend: {…}}
console.log(copy);// {name: "tom", age: 10, friend: {…}}
copy对象的name没有因为obj的name变化而变化,说明该方法实现了深拷贝。缺陷:无法拷贝函数、undefined
方法2:递归层层拷贝,直到基本值类型为止。
function deepCopy(obj){
// 判断是否为引用类型
if(!obj && typeof obj !== 'object'){
throw new Error('type error');
}
const targetObj = Object.prototype.toString.call(obj) == '[object Array]'?[]:{};
for(let key in obj){
let prop = obj[key]; // 避免相互引用造成死循环,如obj.a=obj
if (prop == obj) {
continue;
}
// 只有对象本身的属性才复制
if(obj.hasOwnProperty(key)){
// 如果是引用类型继续向下
if(obj[key] && typeof obj[key] == 'object'){
targetObj[key] = deepCopy(obj[key]);
}else{
targetObj[key] = obj[key];
}
}
}
return targetObj;
}
let a = {
name:'tom',
age:undefined,
friends:['tom','jack','merry'],
sayName(){
console.log(this.name);
}
}
let b = deepCopy(a);
a.age = 20;
a.name = 'tony';
console.log(a);
console.log(b);
b.sayName();
网友评论