function deepClone(origin,target){
var target=target || {}; //防止target为空
var toString=Object.prototype.toString,
arrClass='[object Array]',
objectClass='[object Object]';
for(var prop in origin){
// 判断是否为基本数据类型
// 判断传入的对象属性的属性值是否为object,并且不能为null
if(typeof(origin[prop])=='object'&&origin[prop]!==null){
// 引用类型
// 判断是数组还是对象
if(toString.call(origin[prop])==arrClass){
target[prop]=[];
}else if(toString.call(origin[prop])==objectClass){
target[prop]=={};
}
// 只考虑数组和对象的引用类型
// target[prop]=toString.call(origin[prop])==arrClass? []:{};
// 递归,循环取出对象或者数组中的元素,知道都是基本数据类型
deepClone(origin[prop],target[prop]);
}else{
// 判断是基本数据类型
target[prop]=origin[prop];
}
}
return target;
}
参数1为被克隆的对象,参数2为克隆对象target
var target=target || {};这句的意思是,声明一个变量名为target的变量,值为实参target || { },当我们没有传入参数的时候,第二实参值为undefinde,在进行表达式运算的时候,转为boolean为false,target最后的值为{}一个空对象。
Object.prototype.toString提取获得最初对象类型字符串的方法,后面会用,arrClass和objectClass都是为后面做判断使用的字符串。
遍历被克隆对象origin,首先判断当前项是基本数据类型还是引用数据类型,如果是基本数据类型,函数通过else向下执行,如果不是基本数据类型,那么就进入if判断中,引用数据类型的大块是数组和对象,这里我们判断引用数据类型是数组引用数据类型还是对象引用数据类型,Object.prototype.toString.call(引用数据类型)如果结果为’[[object Array]]'即为对象,如果结果为‘[object Object]’即为对象,判断完成后创建相对于的空数组或空对象,下一步调用函数本身,参数1写入当前引用类型项,参数2写入创建的空数组或者是空对象,这样一层一层的向下,直到最下层都是基本数据类型为止,返回得到的target,一层一层向上返回,最后得到克隆的效果,这个递归的出口为最下层所有数据都为基本数据类型。