深拷贝和浅拷贝
1. 内存地址
Array
, Function
,Object
等等可以认为是除了基本数据类型 String
,Number
,Boolean
,null
,undefined
,Symbol
以外,所有类型都是引用数据类型
引用数据类型存储在堆内存中,在栈中存储了指针,该指针指向堆中该实体的起始地址
当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
let str = 'jsx'; // string
let num = 100; // number
let bool = true; // boolean
let arr = ['html', 'vue']; // array
let fn = function() {
console.log('function')
} // function
let obj = {
name: 'jsx'
}; // object
1-1 基本数据类型的复制
基本类型数据的值存储在栈内存中,各自有自己的栈空间,所以复制后修改值,其它值不会发生变化
let a = 100;
let b = a;
b = 200;
console.log(b); // 200
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mj4Eo7gD-1649323883779)(https://raw.githubusercontent.com/xiaofeilalala/DocsPics/main/imgs/20220322231446.png)]
1-2 引用数据类型的复制
栈内存中存放地址指向堆内存中的对象
引用类型的复制会为新的变量自动分配一个新的值保存在变量中, 但只是引用类型的一个地址指针而已,实际指向的是同一个对象
let obj = {
name: 'jsx'
}
let obj1 = obj;
obj1.name = 'ljj';
console.log(obj)
2. 赋值和深/浅拷贝的区别
这三者的区别如下,不过比较的前提都是针对引用类型:
- 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的
- 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响
- 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响
// 基本数据类型不会影响
let name = 'jsx';
let user = name;
user = 'ljj';
console.log(name, user); // jsx ljj
// 引用类型浅拷贝
let obj = {
name: 'html',
age: 20,
grilfriend: {
name: 'css'
}
}
function lightCopy(obj) {
let target = {
};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
target[key] = obj[key]
}
}
return target;
}
let obj1 = lightCopy(obj);
obj1.grilfriend.name = 'vue';
console.log(obj); // {name: 'html', age: 20, grilfriend: {name: 'vue'}}
console.log(obj1); // {name: 'js', age: 20, grilfriend: {name: 'vue'}}
// 深拷贝
let method = {
user: 'bbc',
info: {
change: true
},
fn: function() {
}
}
let newObj = JSON.parse(JSON.stringify(method));
newObj.info.change = 'ok';
console.log(method);
console.log(newObj);
3. 浅拷贝
3-1 什么是浅拷贝
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址
浅拷贝只拷贝数据对象的第一层,深层次的数据值与原始数据会互相影响
如果其中一个对象改变了这个地址,就会影响到另一个对象
let obj = {
name: 'html',
message: {
info: 'hello'
}
}
function lightCopy(obj) {
let target =