声明变量时
js 引擎会在栈内存中开辟一个以该变量命名的存储空间,若未赋值,则该空间内存的值类型的数据 undefined。
// 在栈内存中开辟了一个名为 a 的存储空间,此时 a 的值为 undefined
let a;
变量赋值时
值类型
直接用数据赋值时,会将数据的值存入该变量命名的空间
// 开辟空间 a,将数字1 存入空间 a 中
let a = 1;
若是通过变量赋值,则会将数据的值复制一份,存入新变量命名的空间中,两个变量内存储的数据相互独立,互不影响。
// 开辟空间 a,将数字1 存入空间 a 中
let a = 1;
// 开辟空间 b,复制一份数字1,将新复制的数字 1 存入空间 b 中
let b = a;
引用类型
直接用数据赋值时,会先将引用类型的数据保存在堆内存中,再将该数据在堆内存中存储的地址存入该变量命名的空间,即变量中存的是数据的引用地址
// 开辟空间 a,将对象 { num:1 } 存在堆内存中,再将对象 { num:1 } 的地址存入空间 a 中
let a = { num:1 };
若是通过变量赋值,则会将数据的引用地址复制一份,存入新变量命名的空间中(浅拷贝),两个变量实际指向的是同一份数据,相互影响。
// 开辟空间 a,将对象 { num:1 } 存在堆内存中,再将对象 { num:1 } 的地址存入空间 a 中
let a = { num:1 };
// 开辟空间 b,将对象 { num:1 } 的地址复制一份,将新复制的对象 { num:1 } 的地址存入空间 b 中
let b = a;
// 将对象中 num 的属性值修改为 2
a.num =2;
// 通过空间 b 中存的地址,找到堆内存中的对象进行打印,此时对象中 num 的属性值已变为 2
console.log(b) // 打印结果: { num:2 }
为什么使用浅拷贝 ?
因为引用类型的数据通常较大,拷贝需要花费更多的时间和空间,浅拷贝可以提升了拷贝速度和内存空间的使用效率,提升了性能。