javascript 對象深拷貝

原生js的對象拷貝都是淺拷貝,若是須要深拷貝則要手動作一些操做json

使用json序列化和反序列化

例子:數組

let obj = {         
  name: 'lizitao',
  msg: {
    age: '2'
  }
}; 
let cp = JSON.parse(JSON.stringify(obj));
console.log(cp);

優勢: 寫起來很是簡單
缺點:侷限性太多了。由於只支持json所支持的那些數據類型。像函數、undefined、正則等這些都是不支持的。遇到環狀結構則會報錯:app

var obj = {
     a: undefined
 };
 console.log(JSON.parse(JSON.stringify(obj)))  // {}
 // 屬性a被自動忽略了

JSON.stringify則會檢測是否存在環,存在則拋出錯誤函數

var obj = {};
obj.child = obj;
JSON.stringify(a)  // Uncaught TypeError: Converting circular structure to JSON

因此咱們只能複雜一點的方式,用遞歸來實現深拷貝this

初版(雛形),能複製簡單對象
const clone = function(source){
    if(source instanceof Object){
        let result = {}
        for (const key in source) {
            result[key] = clone(source[key])
        }
        return result
    } else {
        return source
    }
}

先判斷是否爲對象,非對象則直接返回它的值。若是是對象則新建一個空對象 {},並複製屬性到該對象上。注意屬性的複製是遞歸調用clone函數的:result[key] = clone(source[key]),這樣才能保證每一層都是深拷貝!。
不過它只判斷了是否爲對象,並假設對象都是像{name: value}的形式。若是對象是數組、函數、日期等等就不能正常運行了。因此要判斷對象究竟是哪一種類型的對象,並根據對象具體類型來初始化result,用這樣的形式:code

if(source instanceof Object){
    //...
    if(source instanceof Array){
       //... 
    } else if(source instanceof Function){
       //...
    } else if(source instanceof Date){
       //...
    }
    // 省略許多else if, 判斷越詳細那麼支持的對象類型就越多
    else {
       //...
    }
} else {
    //...
}

因而咱們按照這個思路寫出第二版對象

第二版,支持多種類型的對象
const clone = function(source){
    if(source instanceof Object){
        let result = null
        if(source instanceof Array){
            result = []
        } else if(source instanceof Function){
            result = function(){
                return source.apply(this, arguments)
            }
        } else if (source instanceof Date) {
            result = new Date(source);
        } else {
            result = {}
        }
        for (const key in source) {
            result[key] = this.clone(source[key])
        }
        return result
    } else {
        return source
    }
}

最後要解決的是對象是環的狀況。基本思路是用一個數組來存儲全部複製過的對象,每次調用前先判斷對象是否複製過了,若是複製過就直接返回。遞歸

相關文章
相關標籤/搜索