实现思路
对象类型存储的是对象的引用地址,而把对象的实际内容单独存放,因为对象类型通常比较庞大,这是数据开销和内存开销优化的手段。因此我们不能像原始数据类型一样简单的赋值,而应该遍历数据中的每一个元素,将其中的每一个原始数据类型复制过去,做法如下
- 使用for-in遍历对象中所有属性
- 判断属性是否是原型链上的,不是原型链上的才拷贝
- 判断属性值是原始类型还是引用类型
- 原始类型直接赋值
- 引用类型值不为null时,判断是数组还是对象, 创建对应的空对象或空数组,递归调用函数,将值赋值进去
源代码
/**
* 深度克隆
* @param origin 被拷贝的原对象
* @param target 拷贝出来的对象
* @return 拷贝出来的对象
*/
function deepClone(origin, target) {
var target = target || {};
toStr = Object.prototype.toString;
for(var prop in origin ){
if(origin.hasOwnProperty(prop)){ //不能把原型链上的一起拷贝了
//判断是元素类型还是引用类型
if(typeof(origin[prop]) == 'object' && origin[prop] ){
target[prop] = toStr.call(prop) == '[object Array]' ? [] : {};
arguments.callee(origin[prop], target[prop]); //递归调用
} else {
target[prop] = origin[prop]; //原始类型直接复制
}
}
}
return target;
}
测试数据
var obj = {
name: 'huyao',
card: ['black', 'gold', 'sample'],
child: {
name: 'xioahu',
age: 10,
frends: [{
name: 'xiaowang',
age: 10
},{
name: 'xiaoliu',
age: 9
},{
name: 'longshao',
age: 11
}
]
}
}
var obj1 = {};
deepClone(obj, obj1);
console.log(obj1)
console.log(deepClone(obj, obj1))