克隆分为两种,一种是浅度克隆,另一种为深度克隆。 以下定义看看就行 浅度克隆:原始类型为值传递,对象类型仍为引用传递。 深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修
克隆分为两种,一种是浅度克隆,另一种为深度克隆。
以下定义看看就行
浅度克隆:原始类型为值传递,对象类型仍为引用传递。
深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。
以下为干货:
对于原始类型,克隆表现为简单地值传递。对于对象类型,原理就是通过for..in..遍历原对象,将原对象中的属性赋值到新的对象中。但是由于原对象中的属性不仅只有一层,可能属性中仍包含着新的对象,如果只遍历一次,那么获得的新对象的属性与原对象的深层对象之间自然是仍保持着引用关系,导致新对象与原对象没有实现完全脱离。所以就出现了浅度克隆和深度克隆的区分。
在网上看到了三种方法来实现深度克隆,但其实原理都是使用递归进行深度复制,只是使用的判断数据类型的方法不同。
代码中要注意,判断对象类型时不能使用typeof,因为Array类型和Object类型都会返回Object,但是Array类型和Object类型又是不同的。
以下代码对于所有类型的克隆均可实现
第一种方法:
//返回传递给他的任意对象的类function isClass(o){ if(o===null) return "Null"; if(o===undefined) return "Undefined"; return Object.prototype.toString.call(o).slice(8,-1);}//深度克隆function deepClone(obj){ var result,oClass=isClass(obj); //确定result的类型 if(oClass==="Object"){ result={}; }else if(oClass==="Array"){ result=[]; }else{ return obj; } for(key in obj){ var copy=obj[key]; if(isClass(copy)=="Object"){ result[key]=arguments.callee(copy);//递归调用 }else if(isClass(copy)=="Array"){ result[key]=arguments.callee(copy); }else{ result[key]=obj[key]; } } return result;}
第二种方法:
function clone(obj) { var o; if (typeof obj == "object") { if (obj === null) { o = null; } else { if (obj instanceof Array) { o = []; for (var i = 0, len = obj.length; i < len; i++) { o.push(clone(obj[i])); } } else { o = {}; for (var j in obj) { o[j] = clone(obj[j]); } } } } else { o = obj; } return o;}
第三种方法:仅限于深度克隆对象
Object.prototype.Clone = function(){ var objClone; if (this.constructor == Object){ objClone = new this.constructor(); }else{ objClone = new this.constructor(this.valueOf()); } for(var key in this){ if ( objClone[key] != this[key] ){ if ( typeof(this[key]) == 'object' ){ objClone[key] = this[key].Clone(); }else{ objClone[key] = this[key]; } }} objClone.toString = this.toString; objClone.valueOf = this.valueOf; return objClone;}