在了解浅拷贝和深拷贝前,需要先了解到JavaScript中的不同数据存储方式,不同数据类型的拷贝方式,也是不同的。
基本类型数据和引用数据类型
基本数据类型 String Number Boolean Null Undefined 引用数据类型 Object JS中的变量都是保存到 栈内存 中的 基本数据类型的值是直接在栈内存 中存储
对象是保存到 堆内存 中的 每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的 内存地址(对象的引用),如果两个变量保存的是同一个对象应用,当一个通过一个变量修改属性时,另一个也会因地址指向的原因受到影响。
基本类型数据的拷贝方式
对于基本类型数据的拷贝就是一个值赋值到另一个过程中,修改其中一个值,另一个也不会受到影响。
let a = 1;
let b = a;
a = 3;
console.log(a);
console.log(b);
基本类型数据的拷贝在内存过程大概和下面图:
引用数据的拷贝方式
对于引用数据的拷贝,本质是拷贝了对象的储存地址,拷贝后的变量最终还是指向同一个对象,如果修改其中一个变量中的值,另一个指向对象的变量也会跟着更改。
数组的浅拷贝
let oldArray = [1,4,"木龙","刀圭","意马"];
let newArray = oldArray;
oldArray[0] = "江流";
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);
浅拷贝和深拷贝的概念
浅拷贝:完成拷贝后可能存在彼此之间操作互相影响的就是浅拷贝
深拷贝:完成拷贝后彼此之间操作绝不会有互相影响的就是深拷贝
也有其他解释:浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的
数据都会拷贝出来
深拷贝
JSON.parse()、JSON.stringify()
语法:
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.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;
|