JS-拷贝

123 阅读2分钟

clone

我们想复制一个对象的时候,经常通过赋值实现,但是通常一个变,另外一个也会跟着变。

拷贝的是引用值地址

var person1 = {
	name: 'jackson',
	age: 25,
	sex: 'male'
}
var person2 = person1;
person2.name = 'winwin';
console.log(person1, person2);  //都是winwin

只是多了一个变量指向person1的存储空间


浅拷贝

循环复制增加属性,就不会指向同一个存储空间

因为声明了一个空对象存储,并没有复制地址

var person2 = {};
for(var key in person1){
	person2[key] = person1[key];
}
person2.name = 'winwin';
console.log(person1, person2);

不足:原型链上的自定义属性也会拷贝,并且只处理了属性,没有处理引用值(没有处理引用地址的问题,还是拿的别人的)。

Object.prototype.num = 1;
var person1 = {
	name: 'jackson',
	age: 25,
	sex: 'male',
	son: {
		first: 'ben',
		second: 'willion'
	}
}
var person2 = {};
clone(person1, person2)

person2.name = 'winwin';
person2.son.third = 'bam';
console.log(person1, person2);

function clone(origin, target){
	for(var key in origin){
		target[key] = origin[key];
	}
}

原型链上的自定义属性也会克隆

并且bam在两个person里都添加了,for in循环只处理了第一层的属性,没有处理第二层的引用值,引用值还是会两个一起加

原型链的问题可以弥补,引用值的问题还需要深拷贝

function clone(origin, target){
	var tar = target || {};
	for(var key in origin){
		if (origin.hasOwnProperty(key)) {
			tar[key] = origin[key];
		}		
	}
	return tar;
}

深拷贝

function deepClone(origin, target){
	var target = target || {}, //用户不传值的话
		toStr = Object.prototype.toString,
		arrType = '[object Array]'; //引用值不是数组就是对象
	for(var key in origin){
		if (origin.hasOwnProperty(key)) {
			if (typeof(origin[key]) === 'object' && origin[key] !== null) {
				if (toStr.call(origin[key]) === arrType) {
					target[key] = []; //如果是数组,就新建数组
				}else{
					target[key] = {};
				}
				deepClone(origin[key], target[key]);
			}else{
				target[key] = origin[key]; //不是引用值的话,直接赋值 / 递归出口
			}
		}		
	}
	return target;
}

条件判断可用三目运算符判断

toStr.call(origin[key]) === arrType ? target[key] = [] : target[key] = {};
Object.prototype.num = 1;
var person1 = {
	name: 'jackson',
	age: 25,
	sex: 'male',
	son: {
		first: 'ben',
		second: 'willion'
	}
}
var person2 = deepClone(person1);

person2.name = 'winwin';
person2.son.third = {
	name: 'ten',
	age: 3
};
console.log(person1, person2);

还有一种JSON的方法

var str = JSON.stringify(person1);//将对象转换为字符串
var person2 = JSON.parse(str);//再将字符串转换为对象

但是JSON中是不存在方法的,不建议这么做