前面讲了js变量的基础类型和引用类型,我们来总结一下这两个类型的特点。
基础类型:按值访问,可以操作实际值。
引用类型:值是保存在内存中的对象。js不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时, 实际上是在操作对象的引用而不是实际的对象。
我们再来看栈和堆的存储说明
栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值
和引用类型的地址
堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值
。

由上面的基础,我们再来区分什么是浅拷贝和深拷贝。
浅拷贝
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
基础数据类型的浅拷贝
var a = 1 ;
var b = a ;
b = 2;
a // 1
b // 2
引用类型的浅拷贝
var arr = [1, 2, 3];
var arr2 = arr;
arr2[2] = 4;
console.log(arr)
[1, 2, 4]
深拷贝
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
我们可以借助引用类型的方法进行深拷贝;
数组
for 循环
let arr1 = [1,2,3];
let arr2 = copyArr(arr1);
function copyArr(arr){
let res=[];
for(let i=0,length=arr.length;i<length;i++){
res.push(arr[i]);
}
return res;
}
slice
let arr1 = [1,2,3];
let arr2 = arr1.slice(0);
concat
let arr1 = [1,2,3];
let arr2 = arr1.concat();
扩展运算符
let arr1 = [1,2,3];
let arr2 = [...arr1];
对象也同理
但是要强调一点:ES6新增了Object.assign()
方法
第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象可枚举的自有键并把它们复制到目标对象,最后返回目标对象
assign
是使用=
操作符来赋值,
Object.assign()
只是一级属性复制,比浅拷贝多深拷贝了一层而已。用的时候,还是要注意这个问题
网友评论