深克隆与浅克隆(深克隆的封装)

浅克隆:克隆的时候没有创建新对象,还是共用原来的地址,克隆出来的对象跟着一起变化。

/*浅克隆*/
var arr=[1,2,3,4,5];
var arr2=arr;
arr[0]=100;
console.log(arr2);  //[100, 2, 3, 4, 5]

深克隆:克隆的时候创建了一个新对象,不再共用地址,克隆出来的对象不跟着一起变化。

/*深克隆封装*/
function deepClone(origin,target){
	var target = target || {},
		toStr = Object.prototype.toString,
		arrType = '[object Array]';
	for(var prop in origin){
		if (origin.hasOwnProperty(prop)) {
			if (origin[prop] !== 'null' && typeof origin[prop] === 'object') {
				if (toStr.call(origin[prop]) == arrType) {
					target[prop] = [];
				}else{
					target[prop] = {};
				}
				deepClone(origin[prop],target[prop]);
			}else{
				target[prop] = origin[prop];
			}
		}
	}
}
var obj = {
	name : 'syy',
	age : 12,
	tabs : [1,2,3,4,5],
	hobbies : {
		a : 'a',
		b : [4,5,6,7],
		c : {
			d : 'd',
			e : 'e'
		}
	}
}
var obj1 = {};
deepClone(obj,obj1)
obj.tabs[0]=100;
obj.hobbies.c.d="wxy";
console.log(obj1); //obj1打印出来的值见下图

在这里插入图片描述
有些文章说到深拷贝时说,用slice、concat、扩展运算符也可实现,这是个很大的误区。写个简单的demo,乍一看,很有道理,这里边却有个不易察觉的误区:

var a = [1,2,3];
var b = a.slice(0);
var c = a.concat();
b.push(4); 
c.push(5);
var d = [...a];

console.log(a);   // [1,2,3]
console.log(b);   // [1,2,3,4]
console.log(c);    // [1,2,3,5]
console.log(d);    // [1,2,3]

看到上述打印结果,大家一定以为这么容易就能实现深克隆,上面深克隆的封装还巴拉巴拉写辣么多,装13的么?别急,且往下看,稍微变点形式,就能看出差别了:

var a = [1,2,3,[6,7]];
var b = a.slice(0);
var c = a.concat();
b[3][0] = 100; 
c.push(5);
var d = [...a];

console.log(a);   // [1,2,3,[100,7]]
console.log(b);   // [1,2,3,[100,7]]
console.log(c);    // [1,2,3,[100,7],5]
console.log(d);    // [1,2,3,[100,7]]

可以看到,silce、concat、扩展运算符的写法,外面的引用不共用地址,深层的元素引用却还是共享一个地址。不知道这个小知识点,写项目的时候这个bug少说要花费一两个小时呦!
结论:slice、concat、扩展运算符仅适用于不包含引用对象的一维数组的深拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值