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中是不存在方法的,不建议这么做