let a = { age: 1 } let b = a a.age = 2 console.log(b.age) // 2
从上面的例子能够发现,若是给一个变量赋值一个对象,那么二者的值会是同一个引用,其中一方改变,另外一方也会相应改变。javascript
解决这个问题,能够引入浅拷贝:java
Object.assign
来解决这个问题let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1
let a = { age: 1 } let b = {...a} a.age = 2 console.log(b.age) // 1
一般浅拷贝能解决大部分的问题,可是当遇到,对象里面嵌套一个对象的时候,就须要用到深拷贝了函数
let a = { age: 1, name: { first: 'black' } } let = {...a} a.name.first = 'guyue' console.log(b.name.first) // guyue
这样说明浅拷贝并无对嵌套的对象生效。此时须要深拷贝上场:code
深拷贝最简单的实现办法就是使用JSON.parse(JSON.stringify(object))
来解决。对象
let a = { age: 1, name: { first: 'black' } } let b = JSON.parse(JSON.stringify(a)) a.name.first = 'guyue' console.log(b.name.first) // black
可是当出现如下几种状况的时候,会出现问题:ip
let obj = { a: 1, b: { c: 2 } } obj.c = obj.b obj.d = obj.a obj.b.c = obj.c let newObj = JSON.parse(JSON.stringify(obj)) console.log(newObj) // Uncaught TypeError: Converting circular structure to JSON
报错了,不能解决循环引用对象的问题。ci
let obj = { age: undefined, sex: function(){}, name: 'black' } let newObj = JSON.parse(JSON.stringify(obj)) console.log(newObj) // {name: "black"}
发现只拷贝了name
,而忽略了undefined
和funcion
。get
因此,JSON.parse(JSON.stringify(obj))
遇到这几种状况会出现问题:string
undefined
因此采用下面的方式:io
function deepClone(obj) { let res = obj instanceof Array ? [] : {} for(let k in obj) { res[k] = obj[k] if(typeof obj[k] === Object) { deepClone(obj[k]) } } return res } let obj = { age: undefined, sex: function(){}, name: 'black' } let newObj = deepClone(obj) console.log(newObj) // {age: undefined, sex: ƒ, name: "black"}
能够采用ES2017的新语法:
function copyObject(orig) { return Object.create( Object.getPrototypeOf(orig), Object.getOwnPropertyDescriptors(orig) ); } let obj = { age: undefined, sex: function(){}, name: 'black' } let newObj = copyObject(obj) console.log(newObj) // {age: undefined, sex: ƒ, name: "black"}