方法一:JSON
1、实现
let user = {
name: 'Jerry',
age: 30,
}
let newUser = JSON.parse(JSON.stringify(user))
console.log('user: ', user)
console.log('newUser: ', newUser)
2、优点
(1)简单粗暴:深拷贝
3、缺点
(1)忽略不可枚举的属性
let user = {
name: 'Jerry',
age: 30,
}
Object.defineProperty(user, 'name', {
writable: true,
enumerable: false,
configurable: true,
})
let newUser = JSON.parse(JSON.stringify(user))
console.log('user: ', user)
console.log('newUser: ', newUser)
(2)忽略
symbol类型的属性
let user = {
name: 'Jerry',
age: 30,
[Symbol('desc')]: '666'
}
let newUser = JSON.parse(JSON.stringify(user))
console.log('user: ', user)
console.log('newUser: ', newUser)
(3)无法克隆
原型
let person = {
say() {}
}
let user = {
name: 'Jerry',
age: 30,
__proto__: person
}
let newUser = JSON.parse(JSON.stringify(user))
console.log('user: ', user)
console.log('newUser: ', newUser)
方法二:for..in
1、实现
for (let key in user) {
clone[key] = user[key]
}
2、缺点
(1)不能复制属性的不可配置标志符
let user = {
name: 'Jerry',
age: 30
}
Object.defineProperty(user, 'name', {
configurable: false
})
let newUser = {}
for (let key in user) {
newUser[key] = user[key]
}
console.log('user: ', Object.getOwnPropertyDescriptors(user))
console.log('newUser: ', Object.getOwnPropertyDescriptors(newUser))
(2)忽略不可枚举的属性
let user = {
name: 'Jerry',
age: 30
}
Object.defineProperty(user, 'name', {
enumerable: false,
})
let newUser = {}
for (let key in user) {
newUser[key] = user[key]
}
console.log('user: ', Object.getOwnPropertyDescriptors(user))
console.log('newUser: ', Object.getOwnPropertyDescriptors(newUser))
(3)忽略symbol类型的属性
let user = {
name: 'Jerry',
age: 30,
[Symbol('11')]: '666'
}
let newUser = {}
for (let key in user) {
newUser[key] = user[key]
}
console.log('user: ', Object.getOwnPropertyDescriptors(user))
console.log('newUser: ', Object.getOwnPropertyDescriptors(newUser))
(4)浅拷贝
方法三:Object.assign
Object.assign() 方法将所有可枚举(Object.propertyIsEnumerable() 返回 true)的自有(Object.hasOwnProperty() 返回 true)属性从一个或多个源对象复制到目标对象,返回修改后的对象。
1、实现
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source, {d: 5})
console.log(target); // {a: 1, b: 4, c: 5, d: 5}
console.log(returnedTarget); // {a: 1, b: 4, c: 5, d: 5}
2、缺点
(1)忽略不可枚举的属性
(2)忽略symbol类型的属性
(3)浅拷贝
方法四:Object.defineProperties和Object.getOwnPropertyDescriptors
1、实现
let user = {
name: 'Jerry',
age: 30,
[Symbol('11')]: '666'
}
Object.defineProperties(user, {
'name': {
enumerable: false,
},
'age': {
configurable: false
}
})
const newUser = Object.defineProperties({}, Object.getOwnPropertyDescriptors(user))
console.log('user: ', Object.getOwnPropertyDescriptors(user))
console.log('newUser: ', Object.getOwnPropertyDescriptors(newUser))
2、优点
(1)能复制属性的不可配置标志符
(2)可复制不可枚举的属性
(3)可复制symbol类型的属性
3、缺点
(1)无法克隆原型
let user = {
name: 'Jerry',
age: 30,
}
let person = {
say() {}
}
Object.setPrototypeOf(user, person)
const newUser = Object.defineProperties({}, Object.getOwnPropertyDescriptors(user))
console.log('user: ', user)
console.log('newUser: ', newUser)
(2)浅拷贝
方法五:Object.create
1、实现
let person = {
say() {}
}
let user = {
name: 'Jerry',
age: 30,
__proto__: person
}
const cloneUser = Object.create(Object.getPrototypeOf(user), Object.getOwnPropertyDescriptors(user))
console.log('user: ', user)
console.log('cloneUser: ', cloneUser)
2、优点
(1)能复制属性的不可配置标志符
(2)可复制不可枚举的属性
(3)可复制symbol类型的属性
(4)可复制原型对象
3、缺点
(1)浅拷贝
总结:此调用可以对 obj 进行真正准确地拷贝,包括所有的属性:可枚举和不可枚举的,数据属性和 setters/getters —— 包括所有内容,并带有正确的 [[Prototype]]。