对象是js里重要的基本类型,广义上讲js里万物皆对象。复制一个数据,是一个经常使用的需求,可是相对于基本数据类型如数字,字符串等,对象复制起来要复杂的多。javascript
// 数字的复制
var m = 666
var n = m
console.log(n) // 666
复制代码
对象的复制是没法这样的,觉得这样的复制只是复制了对象的引用java
var o1 = {
m: 666,
n: 'abc'
}
var o2 = o1
console.log(o2.m) // 666
console.log(o2.n) // abc
// 改变o1会致使o2也发生改变
o1.m = 999
o1.n = 'def'
console.log(o2.m) // 999
console.log(o2.n) // def
复制代码
能够看出,当原对象发生改变,复制的对象也会发生改变,这不符合咱们的要求。es6
var copy_1 = function (obj) {
var o
// 检测传入数据的属性,根据数据的类型分别处理
switch (typeof(obj)) {
case 'undefined':
break
case 'string':
o = obj + ''
break
case 'number':
o = obj - 0
break
case 'boolean':
o = !!obj
break
case 'object':
if (obj === null) {
o = null
} else {
if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
o = []
for (let v of obj) {
o.push(copy_1(v))
}
} else {
o = {}
// 遍历对象,并递归遍历对象每一层,而后复制每层属性
for (let v in obj) {
o[v] = copy_1(obj[v])
}
}
}
break
default:
o = obj
}
return o
}
var o1 = {
m: 666,
n: 'abc'
}
var o2 = copy_1(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码
此方法不可复制对象的getter和setter属性,不可枚举属性ui
var copy_2 = function (obj) {
var o
if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
o = []
} else {
o = {}
}
// 使用Object.assign()
return Object.assign(o, obj)
}
var o1 = {
m: 666,
n: 'abc'
}
var o2 = copy_2(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码
此方法不可复制对象的getter和setter属性,不可枚举属性,对象的继承属性spa
var copy_3 = function (obj) {
var o = {}
// 获取原对象全部属性的描述
var des = Object.getOwnPropertyDescriptors(obj)
// 经过对象属性描述建立新对象
Object.defineProperties(o, des)
return o
}
var o1 = {
m: 666,
n: 'abc'
}
var o2 = copy_3(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码
此方法不可复制对象的继承属性prototype
以上三种方法各有各的适用范围,为了达到各类复制需求,能够考虑综合几种方法来达到复制的要求。code