说法是错误的,引用数据类型同时存放在堆与栈里面的,堆中存储对象,栈里面存储对象指向的指针。
赋值:就是对原对象的栈内存地址进行复制
// 对象赋值
let obj1 = {
name: 'Chen',
age: 18,
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = obj1;
= 'Forever';
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj2===>', obj2);
浅拷贝:是对原对象的属性值进行精准复制,如果原对象的属性值是基本类型,那就是值的引用,所以浅拷贝后修改基本类型不会修改到原对象的,如果原对象属性值是引用类型,那么就是对引用类型属性值的栈内存的复制,所以修改引用类型属性值的时候会修改到原对象。
// 浅拷贝
let obj1 = {
name: 'Chen',
age: 18,
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj3 = {...obj1};
= 'Forever';
obj3.hobby[1] = 'swim';
obj3.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj3===>', obj3);
赋值和浅拷贝的区别
- 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的
- 浅拷贝则比赋值多了一层,把对象的值复制一份赋给一个新变量。当对象里的属性值是基础数据类型时,其中一个对象改变属性值,另一个对象不会受到影响;但是当对象里的属性值是引用数据类型时,那么这里面的引用数据类型就会是联动的,其中一个对象改变属性值,另一个对象相应的属性值就会发生改变。
简单的说,浅拷贝就相当于给对象的第一层做了遍历赋值
深拷贝和浅拷贝的区别:浅拷贝主要是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,并对指针指向的内容进行拷贝,经过深拷贝后的指针是指向两个不同地址的指针。
因此一般对无引用类型的属性的兑现拷贝的时候使用浅拷贝就行,对复杂对象包含引用类型属性的时候使用深拷贝。
浅拷贝对象方法:
1.Object.assign({},obj)
要注意当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。


2.obj1={...obj2}
深拷贝对象方法(简单方法):
1.JDON.parse(JSON.stringfy(obj)) 无法拷贝undefined和Symbol,还会出现循环引用问题
2.手写深拷贝
使用for in 遍历传入参数的属性值,如果值是基本类型直接复制,若是引用类型则递归调用本函数(附上引用类型的判断方法:xx instanceOf Object 和Array.isArray(xx)) 存在问题是除了对象和数组,其他引用类型无法拷贝(Date等),Symbol也不能复制
后续继续补充...
function cloneDeep(obj) {
if (!obj instanceof Object) {
return;
}
let newObj = obj instanceof Array ? [] : {};
for (let key in obj) {
// 使用 .hasOwnProperty()判断一个对象是否包含自定义属性而不是原型链上的属性
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key] instanceof Object ? cloneDeep(obj[key]) : obj[key];
}
}
return newObj;
}
















