用js处理数据的时候经常遇到这样一个问题,需要保留原始数据不变情况下,进行一系列数据操作,这时候需要制作一份原始数据的副本数据来进行操作
注意的是引用数据类型和基本数据类型在内存中存储方式是不一样的,只有在引用类型中才会存在深拷贝和浅拷贝的概念,而基本数据类型不会涉及到深拷贝和浅拷贝的问题
基本数据类型和引用数据类型:
基本数据类型的变量作为值保存在栈内存中
而引用数据类型的变量是作为一个指针保存在栈内存中,并且指针指向的是那个保存它数据的堆内存的地址
深拷贝和浅拷贝:
浅拷贝指在拷贝一个变量时,只复制了栈内存,没有复制堆内存
深拷贝指在拷贝一个变量时,复制了栈内存同时也复制了它的堆内存,并且重新生成新的指针
浅拷贝实例:
// 将构造好的数组赋值给另外一个空数组
var a = [1,2,3,4,5]
var b = []
b = a
console.log(a);
console.log(b);
console.log('-----');
b[0] = 9
console.log(a);
console.log(b);
// 输出结果
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
-----
[9, 2, 3, 4, 5]
[9, 2, 3, 4, 5]
/*
得出结论:
以b = a的方式将a的值赋给b
会将两个变量同时指向一个堆内存
所以当修改b的时候
a的值也会跟着b的变化而变化
*/
深拷贝实例:
如果需求是要将上面两个变量改做成深拷贝,则需要添加以下内容
var a = [1,2,3,4,5]
var b = []
b = a.slice()
或
b = a.concat()
或
b = JSON.parse(JSON.stringify(a))
console.log(a);
console.log(b);
console.log('-----');
b[0] = 9
console.log(a);
console.log(b);
// 输出结果
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
-----
[1, 2, 3, 4, 5]
[9, 2, 3, 4, 5]
/*
得出结论:
以上三种方法都可以使b在被赋值时
将a的堆内存一起复制
并重新生成指针
指向新的堆内存
*/
应用分析:
深拷贝复制了原始数据的栈内存和堆内存
并开辟了新的内存空间
因此占用空间会更多
应当避免使用大量的深拷贝
如果要使用深拷贝
应当合理的结合浏览器内存回收机制释放内存