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"}