让你彻底理解JavaScript中深拷贝和浅拷贝的区别在哪里
- 深拷贝
- 浅拷贝
首先我们来了解一下有哪些类型:
基本数据类型:字符串(String)、数值(Number)、布尔值(Boolean)、未定义(Undefine)、空值(null);
引用数据类型:数组(Array)、对象(Object)、函数(Function)。
引用数据类型的值是保存在栈内存和堆内存中的对象。栈区内存保存变量标识符和指向堆内存中该对象的指针。当寻找引用值时,解释器会先寻找栈中的地址。然后根据地址找到堆内存的实体。
什么是深拷贝:
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象。
什么是浅拷贝:
变量保存的不是对象本身,是指向对象的地址,此时改变对象本身的内容,其他变量显示内容也会改变;如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 。
深拷贝和浅拷贝的区别在哪里?
- 深拷贝改变新对象不会影响原对象,他们之间互不影响;
- 浅拷贝基本类型之前互不影响,引用类型其中一个对象改变了地址,就会影响另一个对象。
简单理解:就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
接下来我们用简单的案例来理解一下:
深拷贝:
使用JSON.stringify()方法
const list3= [{name:'张亮'}]
const listCopy2 = JSON.parse(JSON.stringify(list3))
listCopy2[0].name = '王五'
console.log(list3);
console.log(listCopy2);
案例:
function deepCopy(obj5){
if(typeof obj5 !== "object" || obj5 === null){
return obj5
}else if(Array.isArray(obj5)){
var arr = []
for(var i=0;i<obj5.length;i++){
arr.push(deepCopy(obj5[i]))
}
}else if(obj5 instanceof Date){
return new Date(obj5)
}else if(obj5 instanceof String){
return new String(obj5)
}else if(obj5 instanceof Number){
return new Number(obj5)
}else if(obj5 instanceof Boolean){
return new Boolean(obj5)
}else{
var newObj = {}
for(var i in obj5){
newObj[i] = deepCopy(obj5[i])
}
}
}
var obj5 = {
str : "strjkgfd",
num : 13,
arr :[2,4,6,7,56,"dggfd",[2,4.6]],
obj : {a:1,b:2,arr2:["a","b"],obj5:{a:2}},
date : new Date()
}
var obj6 = deepCopy(obj5)
运行结果:
浅拷贝:
使用[...list]方法进行拷贝
// 第一种方法
const list = [{name:'张三'}]
const copylist = [...list]
copylist[0].name = '李四'
console.log(list);
console.log(copylist);
使用slice()方法方法进行拷贝
// 第二种
const list1 = ['张三','李四']
const listCopy = list1.slice() //slice()方法
listCopy.push('王五')
console.log('list:'+ list);
console.log('listCopy:' + listCopy);
使用Array.from()方法方法方法进行拷贝
const list2 = ['张三','李四']
const listCopy1 = Array.from(list2) //Array.from()方法
listCopy1.push('王五')
console.log('list2:'+ list2);
console.log('listCopy1:' + listCopy1);
你理解了吗?