【笔记】深复制与浅复制

深复制与浅复制

浅复制:复制地址。举个栗子,柜子的第一格有一个苹果,A手里有一张写着苹果放置位置的纸条,B将A的纸条抄录了一份,此时苹果还是只有一个,如果B根据纸条写的位置去咬一口苹果,那么,当A再根据纸条去找到苹果时,这个苹果就是被咬过的苹果。

	let a={name:'张三',age:20};
    //这里的a是变量,该变量中是指向堆中{name:'张三',age:20}对象的存储地址
    
    let b=a;  //此时b只复制了a变量中的地址,a与b指向同一个对象
    
    console.log(a);  //{name: "张三", age: 20}
    console.log(b);  //{name: "张三", age: 20}
    console.log(a===b); //true
    
    b.name='b修改了名字';   //通过b修改对象的name属性
    
    console.log(a);  //{name: "b修改了名字", age: 20}
    console.log(b);  //{name: "b修改了名字", age: 20}

以上代码中b只 复制 了a变量中的 地址,a与b指向 同一个对象,因此通过b修改指向对象的属性后输出a,b都是被修改后的对象。

深复制:复制值,即将 复制 对象的 内容 都复制过来,产生一个 新的对象。举个栗子,用放在柜子第一格的苹果a克隆出一个一模一样的苹果b,并将苹果b放在柜子第二格,这两个苹果虽然长得一模一样,但不能说a和b是同一个苹果,就算咬一口苹果b,也只有苹果b上有牙印,苹果a不会受到影响。

console.log({name:'张三'}==={name:'张三'});  //false

深复制的方法

1. JSON.parse(JSON.stringify(obj)) 实现深复制

JSON.stringify将对象转换为字符串,再通过JSON.parse将其还。
注意: 此方法仅适用于一般数据的拷贝,如对象、数组。

let person = {
        name:'张三',   //一级属性
        sex:'男',
        friend:{
            name:'李四',   //二级属性
            sex:'女',
        }
};
let personCopy=JSON.parse(JSON.stringify(person));
console.log(personCopy);

personCopy打印结果:
console.log(personCopy)的输出
验证是否深复制:

personCopy.name = '修改名字';
personCopy.friend.name = '修改朋友名字';
    
console.log(person);
console.log(personCopy);

深复制完成:
修改属性值后person与personCopy的输出

2. Object.assgin() 实现深复制

注意: Object.assgin()只能 深复制一级属性,当二级属性为引用数据类型的时候就是 浅复制二级属性

let person = {
        name:'张三',   //一级属性
        sex:'男',
        friend:{
            name:'李四',   //二级属性
            sex:'女',
        }
};

let newPerson = Object.assign({},person);   //使用Object.assgin()将person复制给newPerson
console.log(newPerson);

newPerson打印结果:
newPerson输出
此时,newPerson将person的一级属性进行了深复制二级属性仍然只进行了浅复制,证明如下:

newPerson.name='改变一级属性';  //newPerson改变一级属性
newPerson.friend.name='改变二级属性';  //newPerson改变二级属性

console.log(person);  
console.log(newPerson);  

深复制一级属性,二级属性仍为地址:
修改一二级属性后的输出

3. for in 递归实现深复制

let thisObj = {
	name:'张三',
	like:{
    	ball:'篮球',
    	eat:'西红柿炒鸡蛋',
	}
};

//写一个递归深复制的方法
function clone(obj) {
    let newObj = {};
    for (let key in obj){
        if (typeof obj[key]==='object'){  //如果obj的该项数据类型依然为对象
            newObj[key]=clone(obj[key]);  //调用自己,该项再次进入判断、复制
        }else {
            newObj[key] =obj[key]
        }
    }
    return newObj;
}
    
let newObj = clone(thisObj);
console.log(thisObj); 
console.log(newObj);  

复制后打印结果:
复制后输出
验证是否深复制:

newObj.name='修改名字';  //修改一级属性
newObj.like.ball='修改篮球';   //修改二级属性

console.log(thisObj);  
console.log(newObj); 

深复制完成:
修改后输出
4. jquery的extend方法实现深复制

$.extend( [deep ], target, object1 [, objectN ] )

deep : 布尔值,默认为false(不支持第一个参数传递false),为true时为深拷贝,为false时不会深度合并对象;
target: Object类型 目标对象,其他对象的成员属性将被附加到该对象上;
object1objectN: Object类型 被合并的对象。

false举例:

let newPerson = {};
$.extend(newPerson,person);

console.log(newPerson);
console.log(newPerson===person);

输出:
输出
验证未深度合并:

newPerson.name='修改';
newPerson.friend.name='修改';

console.log(person);
console.log(newPerson);

修改后输出
true举例:

let newPerson = {};
    $.extend(true,newPerson,person);
    
    console.log(newPerson);
    console.log(newPerson===person);

输出:
输出
验证深复制:

newPerson.name='修改';
newPerson.friend.name='修改';

console.log(person);
console.log(newPerson);

验证深复制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章