js 多层深拷贝

背景(数组为例):

js数组复制最有效的方法是直接使用slice和concat方法

var testA = [1, 3, 5];
var copya = [].slice.call(testA);
console.log(testA[0]);//1 
copya[0] = 2;
console.log(testA[0]);//1 

var testAA = [[1]];
var copyaa = [].slice.call(testAA);
console.log(testAA[0][0]);//1
copyaa[0][0] = 2;
console.log(testAA[0][0]);//2 问题出现

原因分析:只复制了一维,内部仍是引用;

解决:

先写个curry化 用来判断类型 seajs中也是这种 简单方便 后面会用到

var toString = Object.prototype.toString;
var isType = function(type){ //curry化
	return function(obj){
		return toString.call(obj) == "[object " + type + "]";//例如 "[object Array]"
	}
}
var isArray = isType("Array");
var isObject = isType("Object");

定义几个变量用来测试

var testOA = {a:[1]};
var testAO = [{a:1}];
var testOO = {a:{b:1}};
var testAA = [[1]];

先做下Object的处理:

function copyO(obj){//剥离Object
	var ret = {}
	if(isObject(obj)){ 
		for(var key in obj){
			if(obj.hasOwnProperty(key)){
				var child = obj[key];
				ret[key] = child
				if(isObject(child)){
					ret[key] = arguments.callee(child);
				}
			}
		}
	}else{
		ret = obj;
	}
	return ret;
}

测试结果:

var copyoo = copyO(testOO);
copyoo.a.b = 2;
copyoo.log(testOO.a.b);//1
copyoo.a = null;
console.log(testOO.a);//Object {b: 1}

再做数组的处理:

function copyA(obj){
	var ret = {};
	if(isArray(obj)){
		ret = [].slice.call(obj);
		for(var i = 0; i < ret.length; i++){
			ret[i] = arguments.callee(ret[i]);
		}
	}else{
		ret = obj;
	}
	return ret;
}

测试结果:

var copya = copyA(testAA);
copya[0][0] = 2;
console.log(testAA[0][0]);//1
copya[0].length = 0;//
console.log(testAA[0]);//[1]

合并:

function deepCopy(obj){
	var ret = {};
	if(isArray(obj)){
		ret = [].slice.call(obj);
		for(var i = 0; i < ret.length; i++){
			ret[i] = arguments.callee(ret[i]);
		}
	}else if(isObject(obj)){
		for(var key in obj){
			if(obj.hasOwnProperty(key)){
				var child = obj[key];
				ret[key] = arguments.callee(child);
			}
		}
	}else{
		ret = obj;
	}
	return ret;
}

测试结果:

var copyoa = deepCopy(testOA);
copyoa["a"][0] = 2;
console.log(testOA["a"][0]);//1 
copyoa["a"] = null;//
console.log(testOA["a"]);//[1]

var copyao = deepCopy(testAO);
copyao[0]["a"] = 2;
console.log(testAO[0]["a"]);//1
copyao[0].length = 0;//
console.log(testAO[0]);//Object {a: 1}

可以继续合并写法,这里不做了。。

你可能感兴趣的:(js 多层深拷贝)