1.浅克隆
直接将存储在栈中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址。
function clone(Origin,Target){
var Target = Target || {}
for(var prop in Origin){
Target[prop] = Origin[prop]
}
return Target;
}
var a = {
name:'wcc',
age:24,
sex:{
male:'true',
female:'true'
}
}
var b = clone(a);
b.sex.male = 'false';
b.age = 18;
console.log(b.sex.male,a.sex.male,b.age,a.age)//false false 18 24
可以发现使用浅克隆,如果修改的是引用类型,则原来的对象也会修改,若修改的基本数据类型则不会影响。
2.深克隆
把数据赋值给对应的变量,从而产生一个与源数据不相干的新数据(数据地址已变化)。深克隆是克隆对象各个层级的属性。
步骤:
1遍历对象
2.判断是不是原始值
3.判断是数组还是对象
4,.建立相应的数组或者对象
5.递归
function deepClone(Origin, Target) {
var Target = Target || {};
for (var prop in Origin) {
if (Origin.hasOwnProperty(prop)) {//如果返回false则说明为原型上的属性,不用拷贝
if (Origin[prop] !== 'null' && typeof (Origin[prop]) === 'object') {
if (Object.prototype.toString.call(Origin[prop]) === '[object Array]') {
Target[prop] = [];
} else {
Target[prop] = {};
}
//也可以简写为一行代码赋值
//Target[prop] = Object.prototype.toString.call(Origin[prop]) === '[object Array]' ? [] :{}
deepClone(Origin[prop], Target[prop]);//递归
} else {
Target[prop] = Origin[prop];
}
}
}
return Target;
}
var a = {
name: 'wcc',
age: 24,
sex: {
male: 'true',
female: 'true'
}
}
var b = {};
deepClone(a, b)
b.sex.male = 'false';
b.age = 18;
console.log(b.sex.male, a.sex.male, b.age, a.age)//false true 18 24
如果obj里有RegExp
、Error
对象,还需做其他的处理,除此之外还有一种简单的方法
var b = JSON.parse(JSON.stringify(a));
使用上述方法时需要注意几点:
1、如果obj里面有时间对象,则JSON.stringify
后再JSON.parse
的结果,时间将只是字符串的形式。而不是时间对象
2、如果obj里有RegExp
、Error
对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined
,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()
只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))
深拷贝后,会丢弃对象的constructor
;
6、如果对象中存在循环引用的情况也无法正确实现深拷贝;
若只是克隆数组,也可以使用数组的concat方法。