Javascript深度拷贝

279 阅读1分钟

这里用递归的思想进行JS对象的深度拷贝,并进行封装,思路如下

  1. 判断是不是原始值 使用方法:typeof()/object

  2. 判断是数组还是对象 使用方法: instanceof toString constructor

  3. 建立相应的数组或对象

  4. 循环递归

	function deepClone(origin,target){
		var target = target || {},
			toStr = Object.prototype.toString,
			arr = "[object Array]";

		for(var prop in origin){
			if(origin.hasOwnProperty(prop)){ //选择自己的属性
				if(origin[prop] !== 'null' && typeof(origin[prop]) == 'object'){//区分原始值和引用值
					if(toStr.call(origin[prop]) == arr){//区分数组和对象
						target[prop] = [];//建立数组
					}else{
						target[prop] = {};//建立对象
					}
					deepClone(origin[prop],target[prop]); //循环递归
				}else{
					target[prop] = origin[prop];
				}
			}
		}
		return target;
	}

代码可以将中间target[prop]赋值操作用三目运算符简化如下:

target[prop] = (toStr.call(origin[prop]) == arr) ? [] : {};

因此 简化后的深度拷贝的代码最后如下:
function deepClone(origin,target){
    var target = target || {},//容错
    toStr = Object.prototype.toString,//.call
    arr = "[object Array]";//数组原型

    for(var prop in origin){
        if(origin.hasOwnProperty(prop)){//判断是否是自己的属性
            if(origin[prop] !== 'null' && typeof(origin[prop]) == 'object'){//判断引用值还是原始值
	        target[prop] = (toStr.call(origin[prop]) == arr) ? [] : {};//判断是数组还是对象 然后相应建立数组/对象
		deepClone(origin[prop], target[prop]);//循环递归
	    }else{//原始值
		target[prop] = origin[prop];
	    }
         }
    }
    return target;
}

最后,我们可以创建两个对象来进行深度拷贝
var obj1 = {
    name : 'sunny',
    age : 100,
    sayName : function(){
    console.log(this.name);
    }
}
var obj2 = {};

执行拷贝

deepClone(obj1, obj2);//放入源对象和拷贝对象