要理解深浅拷贝,就要先知道js的数据类型有哪些。分为基本数据类型(string,number,undefind,null,symbol,boolean)和引用数据类型(obj,array,function)
其实通俗来讲就是定义一个变量a,然后赋值给变量b ,改变变量b看看a的值是否改变,ab的值都改了 说明是浅拷贝,b改a不改就是深拷贝。
基本数据类型以值得形式存储在栈中,操作的变量是值,而引用类型的值是存储在堆中,以地址来操作变量,也就是说,基本类型拷贝之后是重新在栈中开辟一个空间,两者不干扰,所以基本类型不分深浅拷贝。
但是引用类型分,浅拷贝就是,引用类型只是在栈中开辟了一个空间把变量名储存在了栈中,但是值存在了堆内存中不会被重新开辟,所以这两个空间指向的还是同一个地址(堆内存中的这个值)。
let a1 = 2
let a2 = a1
console.log(a2) //2
a2 = 3
console.log(a2) //3
console.log(a1) //2
//这就说明了基本类型其实不分深浅拷贝
我们再来看引用类型的拷贝
let obj1 = {
name: 'zhangsan',
age: 12,
hobby:['1','2']
}
let obj2 = obj1
obj2.name = 'lisi'
console.log(obj1) // obj1 结果 {name: "lisi", age: 12, hobby: Array(3)}
//age: 12
//hobby: (3) ["1", "2"]
//name: "lisi"
//__proto__: Object
console.log(obj2) // obj2 结果 {name: "lisi", age: 12, hobby: Array(3)}
//age: 12
//hobby: (3) ["1", "2"]
//name: "lisi"
//__proto__: Object
我们让obj1赋值给obj2,发现改动了obj2的值,obj1的值同样改变了,这是因为他们虽然在栈中开辟了内存,但是指向了同一个地址,而引用类型是通过地址来操作的。
所以我们要是想深拷贝的话要这样做
let obj1 = {
name: 'zhangsan',
age: 12,
hobby:['1','2']
}
let obj2 = obj1
let obj3 = {}
obj3.name = obj1.name
obj3.age = obj1.age
obj3.hobby = obj1.hobby
obj2.name = 'lisi'
obj2.hobby = ['1','2','3']
console.log(obj1)
console.log(obj2)
console.log(obj3)
let obj1 = {
name: 'zhangsan',
age: 12,
hobby: ['1', '2']
}
let obj2 = obj1
let obj3 = {}
// obj3.name = obj1.name
// obj3.age = obj1.age
// obj3.hobby = obj1.hobby
var deepClone = function(obj) {
//把对象转成字符串再转成对象,缓存到返回值中
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj)
return objClone
}
obj3 = deepClone(obj1)
obj2.name = 'lisi'
obj2.hobby = ['1', '2', '3']
console.log(obj1)
console.log(obj2)
console.log(obj3)