深度克隆与浅度克隆

上星期再次研究了一下以前不太清楚的深度克隆,经过连续的写了3次之后终于清晰了一点,记录一下思路。

show me my code

var user={
    name:'姓名',
    gender:'性别',
    Tags:['标签1','标签2']
}

顾名思义,浅度克隆就是指复制啦~

Object.prototype.clone=function(){
    var newObj={};
    for(var key in this){
        if(this.hasOwnProperty(key)){
            newObj[key]=this[key];
        }
    }
    return newObj;
};
var jack=user.clone();
jack.name='jack';
jack.gender='男';
jack.Tags.push('男神');

结果如下:
深度克隆与浅度克隆_第1张图片

ok,我们这里就完成了浅度克隆了,由于我是对整个Object的原型写函数来继承的,所以我在循环内判断了一下属性是否为自身的自有属性,是的话才能复制,解决了会继承复制clone函数的小问题,如果不判断,在结果中会出现clone函数,因为我们这里是对所有对象原型写的继承函数。

那么浅度克隆的问题在哪了,接下来大家就会看到了
假如这时候又多了个妹子

var mary=user.clone();
mary.name='mary';
mary.gender='女';
mary.Tags.push('女神');

结果如下:
深度克隆与浅度克隆_第2张图片

问题显而易见,图中对象顺序依次为mary、jack、原对象,很明显我们想要的效果其实是jack在Tags中是['标签1','标签2','男神'],mary的Tags是['标签1','标签2','女神'],而现状是全部的Tags都变为了['标签1','标签2','男神','女神'],原对象也是,而造成这个问题的原因就是数组是引用类型的= =…这个是基础知识,我想大家都是知道的,所以简单的赋值只是将数组地址赋给了新对象而已,真正引用和更改的仍然是原对象中的数组;

那么解决方法已经很明显了,判断一下是否为引用类型,将引用类型内的元素都赋值就好,利用递归函数就可以巧妙的解决,这就是深度克隆的原理了,下面上深度克隆demo:

Object.prototype.deepClone=function(){

    var newObj = this.constructor == Array?[]:{};//判断克隆对象构造函数为数组

    for(var key in this){
        if(this.hasOwnProperty(key)){
            if(typeof this[key] == "object"){
                newObj[key] = this[key].deepClone();
            }
            else{
                newObj[key] = this[key];
            }
        }
    }  
    //如果是构造函数的情况请加上,不然父深度克隆后的父链并不会指向原构造函数而是Object
    //  newObj.__proto__ = this.__proto__;
    return newObj;
};

var kalista = user.deepClone();
kalista.name='卡利斯塔';
kalista.gender='女';
kalista.Tags.push('LOL');
console.log(kalista);

var jugg=user.deepClone();
jugg.name='剑圣';
jugg.gender='男';
jugg.Tags.push('DOTA');
console.log(jugg);

结果如下:
深度克隆与浅度克隆_第3张图片

完成~我写的函数还是比较简单的,我就不说明了,原理在上面也说过了,实现过程就跟原理所说的一样,需要注意的只是数组的typeof为object与记得递归后的赋值而已,over~

你可能感兴趣的:(js的一些知识分享)