利用JSON
var obj1 = {
a: 1,
b: '2',
c: [1,2]
}
var obj2 = JSON.parse(JSON.stringify(obj1))
obj2.a = 3
console.log(obj1) // { a: 1, b: '2', c: [ 1, 2 ] }
console.log(obj2) // { a: 3, b: '2', c: [ 1, 2 ] }
JSON不能处理的数据类型:
- Function、 undefined、Symbol会丢失
- Date(转换后变成字符串)、RegExp和Error(转换后变成空对象{})
- NaN、Infinity和-Infinity 转换后变成null
- 只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
Object.assign
var obj1 = {
a: 1
}
var obj2 = {
b: 2
}
Object.assign(obj1, obj2)
console.log(obj1) //{ a: 1, b: 2 }
console.log(obj2) // { b: 2 }
弊端:当多层嵌套的属性为对象时依旧只是拷贝了对象的引用,如下
var obj1 = {
a: 1
}
var obj2 = {
b: 2,
c: {
cc: 9
}
}
Object.assign(obj1, obj2)
obj2.c.cc = 0
console.log(obj1) // { a: 1, b: 2, c: { cc: 0 } } obj1和obj2的c属性指向同一个对象
递归拷贝
JavaScript内置的引用类型:
Array、Date、Error、Function、Object、RegExp
以下只考虑了数组、原装Object的情况
function deepClone(val) {
if(val.constructor == Object) {
let obj = {}, keys = Object.keys(val)
for(let i = 0; i < keys.length; i++) {
obj[keys[i]] = deepClone(val[keys[i]])
}
return obj
} else if (Array.isArray(val)) {
return [].concat(val)
} else {
return val
}
}
var obj1 = {
a: 2,
b: {
bb: 22
}
}
var obj2 = deepClone(obj1)
obj1.b.bb = 99
console.log(obj1) // { a: 2, b: { bb: 99 } }
console.log(obj2) // { a: 2, b: { bb: 22 } }