在了解浅拷贝和深拷贝前,需要先了解到JavaScript中的不同数据存储方式,不同数据类型的拷贝方式,也是不同的。
基本数据类型
String Number Boolean Null Undefined
引用数据类型
Object
JS中的变量都是保存到 栈内存
中的
基本数据类型的值是直接在栈内存
中存储
对象是保存到 堆内存
中的
每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的 内存地址(对象的引用),如果两个变量保存的是同一个对象应用,当一个通过一个变量修改属性时,另一个也会因地址指向的原因受到影响。
对于基本类型数据的拷贝就是一个值赋值到另一个过程中,修改其中一个值,另一个也不会受到影响。
let a = 1;
let b = a; //把a的拷贝到b
a = 3;
console.log(a); //3
console.log(b); //1
对于引用数据的拷贝,本质是拷贝了对象的储存地址,拷贝后的变量最终还是指向同一个对象,如果修改其中一个变量中的值,另一个指向对象的变量也会跟着更改。
数组的浅拷贝
let oldArray = [1,4,"木龙","刀圭","意马"];
let newArray = oldArray;//进行拷贝
oldArray[0] = "江流";//修改oldArray的值
console.log("oldArray:",oldArray);
console.log("newArray:",oldArray);
数组也是对象,这就是对象的一种浅拷贝方式。
引用类型数据的拷贝在内存过程大概下面图一样:
当我们修改oldArray[0] = "江流"
的时候,因为在拷贝的时候只是将oldArray所指向的地址赋值给newArray,当通过oldArray去修改堆空间的中值时,也会导致打印newArray的值也会发生改变。这种方式就是浅拷贝。
对象的浅拷贝
var oldObj = {
name:"心猿",
age:2000
}
var newObj = oldObj;//浅拷贝
oldObj.age = 5000;//修改年龄
console.log("oldObj:",oldObj);
console.log("newObj:",newObj);
浅拷贝:完成拷贝后可能存在彼此之间操作互相影响的就是浅拷贝
深拷贝:完成拷贝后彼此之间操作绝不会有互相影响的就是深拷贝
也有其他解释:浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的
数据都会拷贝出来
语法:
var oldObj = {
name: "心猿",
age: 2000
}
var newObj = JSON.parse(JSON.stringify(oldObj));//拷贝
newObj.age = 5000;//修改年龄
console.log("oldObj:", oldObj);
console.log("newObj:", newObj);
粗暴简单,但是也有缺点。
缺点:
可能会影响数剧,函数无法通过这个拷贝,日期类型的数据会变成字符串。
思路:
在对属性值进行拷贝的时候,先判断属性值的类型,如果是对象,就用递归调用深拷贝函数,如果不是,就直接拷贝。
function deepCopy(obj) {
if (typeof obj[key] === 'object') return;
if (Array.isArray(obj)) {//判断是否是数组还是对象
var newObj = [];
}
else {
var newObj = {};
}
for (var key in obj) {
if (typeof obj[key] === 'object' && !(obj[key] instanceof Date)) {
newObj[key] = deepCopy(obj[key]);//使用递归进行拷贝
}
else {
newObj[key] = obj[key];
}
}
return newObj
}
测试代码:
var oldObj = {
name: "心猿",
gender: "男",
age: 2000,
power: {
skill: "七十二变"
}
}
var newObj = deepCopy(oldObj);//调用深拷贝
//修改oldObj中的属性值不会改变newObj中的属性值
oldObj.name = "意马";
oldObj.age = 1500;
oldObj.power.skill = "化身为白龙";
console.log("oldObj:", oldObj);
console.log("newObj:", newObj);
/*----------------------深拷贝代码---------------------------------*/
function deepCopy(obj) {
if (typeof obj[key] === 'object') return;
if (Array.isArray(obj)) {//判断是否是数组还是对象
var newObj = [];
}
else {
var newObj = {};
}
for (var key in obj) {
if (typeof obj[key] === 'object' && !(obj[key] instanceof Date)) {
newObj[key] = deepCopy(obj[key]);//使用递归进行拷贝
}
else {
newObj[key] = obj[key];
}
}
return newObj
}
function deepCopy(obj) {
if (typeof obj !== 'object') return;
let result = obj instanceof Array ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = typeof obj[key] === 'object'
&& !(obj[key] instanceof Date) ? deepCopy(obj[key]) : obj[key];
}
}
return result;