如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
1. 如果是基本数据类型,名字和值都会储存在栈内存中
var a = 1;
b = a;
当然,这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。
2. 如果是引用数据类型,名字存在栈内存中,值存在堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值
比如浅拷贝:
当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。
而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。
那,要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,岂不就达到深拷贝的效果了
3. 实现浅拷贝的方法
(1)for···in只循环第一层
(2)Object.assign方法
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a)
(3)直接用=赋值
let a=[0,1,2,3,4],
b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);
4. 实现深拷贝的方法
(1)采用递归去拷贝所有层级属性
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
结果:
(2) 通过JSON对象来实现深拷贝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
缺点: 无法实现对对象中方法的深拷贝,会显示为undefined
(3)通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4];
var newArray = $.extend(true,[],array);
(4)lodash函数库实现深拷贝
let result = _.cloneDeep(test)
(5)Reflect法
(6)手动实现深拷贝
let obj1 = {
a: 1,
b: 2
}
let obj2 = {
a: obj1.a,
b: obj1.b
}
obj2.a = 3;
alert(obj1.a);
(7)如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({}, obj);
(8)用slice实现对数组的深拷贝
(9)用concat实现对数组的深拷贝
(10)直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i];
(11)使用扩展运算符实现深拷贝