前言
拷贝这个词大家都懂,今天就聊聊什么是深拷贝和浅拷贝
一、简单了解浅拷贝和深拷贝
1.1 浅拷贝
就拿一个案例来讲:比方说我们生活中使用的信用卡,信用卡有主卡和副卡之分,在使用主卡进行消费时,副卡的额度也会发生变化,副卡进行消费时,也会影响到主卡。这就是一个浅拷贝的案例。
1.2 深拷贝
谈到深拷贝,我们就不得不聊一个人,那就是旗木卡卡西,一个copy界的大神,一生复制了无数的忍术,他复制了别人的忍术,但并不会影响到别人使用这个忍术,这就是深拷贝。
二、代码中浅拷贝和深拷贝
js中的数据类型包含:基本数据类型和引用数据类型
基本数据类型:字符串(string)、数值(number)、布尔值(boolean)、undefined、null ;
引用数据类型:对象(Object)、数组(Array)、函数(Function);
对基本数据类型进行复制,并重新赋值,并不会影响到原来的变量,这就是深拷贝。
let myname = '提灯寻猫';
let age = myname;
age = 22;
console.log(myname); //提灯寻猫
console.log(age); //22
myname这个变量会在内存中开辟一个地址,存储一个值为提灯寻猫,age这个变量复制了myname所以他们指向的都是同一个地址,同时也指向同一个值,但对age重新赋值时,会在内存在开辟一个地址来存储另一个值22。
对引用数据类型进行复制,并重新赋值,这样会影响到原来的变量,这就是浅拷贝。
let obj1 = {
myname: "提灯寻猫",
age: 12
}
let obj2 = obj1;
obj2.age = 22;
//里面的age都变成22
console.log(obj1);
console.log(obj2);
对于引用数据类型来说,就有了堆和栈的说法,obj1会开辟一个内存地址,与值相对应(这就是栈),但这个内存地址的值又会被分配到另一个地址,在另一个地址中又创建了对应的值(也就是堆),obj2在进行复制时,就会通过栈一路找到堆进行复制,一旦修改,那么obj1和obj2都会受影响,因为它们指向的都是同一个地址。
三、concat、slice和Arry.form
concat、slice和Arry.form这些都是数组中的方法,使用这些方法就可以完成拷贝
concat
这个方法会创建一个拷贝当前数组的副本,然后把参数添加到副本末尾,如果不添加参数,就相当于拷贝副本,最后返回新构建的数组.
let list = ['上海', '加油'];
let copylist = [].concat(list);
copylist.push('中国')
console.log(list); //上海,加油
console.log(copylist); //上海,加油,中国
slice
不给slice传入参数,会返回一个新的数组,并且包含从头到尾的所有元素,即使后续对复制的数组进行元素添加也不会影响原数组.
let list = ['上海', '加油'];
let copylist = list.slice();
copylist.push('中国')
console.log(list);
console.log(copylist);
Arry.form
使用方式和上面的差不多,就不多做阐述.
let list = ['上海', '加油'];
let copylist = Array.from(list);
copylist.push('中国')
console.log(list);
console.log(copylist);
挖的坑
从上面的演示中,大家都以为是脱离了浅拷贝,实则不然,它们还是浅拷贝
let list = ['上海', '加油', { name: "一切都会过去的" }];
let copylist = Array.from(list);
copylist.push('中国')
copylist[2].name = '都会好起来的'
console.log(list);
console.log(copylist);
如果将数组中的数据改为引用数据类型,那么只要复制变量中修改内部的元素的值,那么原数组中的值也会发生变化,因为改为引用数据类型,里面的变量还是指向同一个地址
解决方法
使用JSON的方法完成深拷贝,先使用JSON.stringify()将JS对象转换为JSON字符串,在使用JSON.parse(),将JSON字符串转换成JS对象,这样得到的就是一个全新JS对象,与之前的内存地址不相连.
let list = ['上海', '加油', { name: "一切都会过去的" }];
let copylist = JSON.parse(JSON.stringify(list))
copylist.push('中国')
copylist[2].name = '都会好起来的'
console.log(list);
console.log(copylist);
