原生JS实现深拷贝

    说到深浅拷贝的问题,其实就是基本类型和引用类型数据拷贝的问题,再深一点就是栈内存和堆内存的区别。

栈内存

    保存基本数据类型或者引用类型数据的地址指针。

堆内存

    保存对象本身。

    所谓的深拷贝就是在内存中单独为该变量开辟一个存储空间。所以对于基本数据类型来说他的任何赋值都深拷贝,因为在栈内存中,数据的大小是固定,不可变的,变量一旦声明就会在内存中在栈内存中开辟一个新的空间。常说的深拷贝是针对于引用类型的。引用类型在栈内存中只保存了一个指向堆内存的指针,所以一般我们在将一个引用类型赋值给另外一个变量的时候,实际上是将这个引用类型在栈内存中指针赋值给了这变量,而最终这个变量指向的堆内存中的同一个对象。
这里写图片描述
举例:

var obj1 = {name:"wangyy"};
var obj2 = obj1;
obj2.name="wangjunjie";
console.log("obj1:",obj1);
console.log("obj2:",obj2);
运行结果:obj1:{name:"wangjunjie"}
         obj2:{name:"wangjunjie"}

    发现在改obj2的时候obj1也跟着改变了,这就是他们指针指向的是同一个内存对象,所以改也是改的同一个对象。但这不是我们希望的赋值 ,我们希望在赋值结束后彼此之前再无瓜葛,那我们应该怎样实现呢?
好了不多说了,上代码了。

方法一:

Object.assign();

var target = {};
var source = {name:"wangyy"}
Object.assign(target,source);
target.name="wangjunjie";
console.log("target:",target);
console.log("source:",source);

运行结果:target:{name:"wangjunjie"}
         source:{name:"wangyy"}

    貌似可以实现深拷贝,在这种情况下也确实能达到我们的目的,但是这种方式是有缺陷的,当对象的属性值也是一个对象的时候,它几现原形了。

var target = {};
var source = {name:"wangyy",family:{mother:"wuxl","father":"wangxy"}}
Object.assign(target,source);
target.family.sister="wanghm";
console.log("target:",target);
console.log("source:",source);

    通过运行结果可以发现Object.assign只能对于像上面那种简单对象可以实现深拷贝,对于复杂对象就无能为力了。

方法二:

将对象转成字符串:

var target = {};
var source = {name:"wangyy",family:{mother:"wuxl","father":"wangxy"}}
target = JSON.parse(JSON.stringify(source ))
target.family.sister="wanghm";
console.log("target:",target);
console.log("source:",source);

    哎!好像可以实现呢,而且也是想对比较号实现的。但是如果出爱心下面这种情况就凉凉了

var target = {};
var source = {
         name:"wangyy",
         family:{
                  mother:"wuxl",
                  father:"wangxy",
                }
         }
target = JSON.parse(JSON.stringify(source ))
target.family.sister="wanghm";
console.log("target:",target);
console.log("source:",source);

    运行后我们发现source中的func属性不见了。所以这种方式还是有局限性的,必须是标准格式的JSON数据。

方法三:

    看来向上面这种一步到位实现深拷贝是不显示了,那下面就专门写一个深拷贝的方法来实现:

function deepClone(data){
    if(!data|!(datainstanceof Object)|(typeof data=="function")){
         return data||undefined;
    }
    var constructor = data.constructor;
    var result = new constructor();
    for(var key in data){
        if(data.hasOwnProperty(key)){
           result[key]=deepClone(data[key]);
        }
    }
    return result;
}

本质就是区分基本数据类型和引用数据类型,然后进行递归操作,over!

猜你喜欢

转载自blog.csdn.net/wang839305939/article/details/80819132
今日推荐