上星期再次研究了一下以前不太清楚的深度克隆,经过连续的写了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('男神');
结果如下:
ok,我们这里就完成了浅度克隆了,由于我是对整个Object的原型写函数来继承的,所以我在循环内判断了一下属性是否为自身的自有属性,是的话才能复制,解决了会继承复制clone函数的小问题,如果不判断,在结果中会出现clone函数,因为我们这里是对所有对象原型写的继承函数。
那么浅度克隆的问题在哪了,接下来大家就会看到了
假如这时候又多了个妹子
var mary=user.clone();
mary.name='mary';
mary.gender='女';
mary.Tags.push('女神');
结果如下:
问题显而易见,图中对象顺序依次为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);
结果如下:
完成~我写的函数还是比较简单的,我就不说明了,原理在上面也说过了,实现过程就跟原理所说的一样,需要注意的只是数组的typeof为object与记得递归后的赋值而已,over~