如何深度複製一個javascript對象

前言json

最近有人問我,如何將一個對象複製一份,由於他遇到了一個需求,須要將後端獲取的數據,保存一份,原始數據會由於交互而發生變化,最終須要對比兩份數據的異同。
他是一個剛入行的小朋友,他的實現方式就是新聲明瞭一個變量,而後將數據賦值給了變量。本覺得這就ok了,結果修改原數據,複製出來的變量中的內容,依然發生了變化。
在此,整理一下。(大中小)牛略過,僅爲幫助新人,聊以解憂。
後端

 

知識鋪墊,值類型,與引用類型數組

咱們用一個新的概念來理解這兩種類型,連鎖店連鎖店的鑰匙函數

1. 類型包含以下:number,string,boolean,undefind,null;spa

    變量的交換如同新開了一家連鎖店,店面統一,但實際上新店與舊點之間,互無影響,各自運營,獨立結算。 prototype

 

var flagship  = 'xx連鎖店'; //當前爲旗艦店
var shop1 = flagship;      //第一家連鎖店
var shop2 = flagship;      //第二家連鎖店

 

2. 引用類型包含以下:對象,數組,函數code

    變量的交換等於現有一家店面的鑰匙(變量地址引用)複製給了另一個老闆,此時兩我的共同管理一家門店,兩我的的行爲均可能對着一間門店的運營形成影響。對象

var boss1 = {shop:'xx連鎖店','state':'開業中'}
var boss2 = boss1;//複製了一把鑰匙給boss2
boss2.state = '裝修中'; //boss2將門店升級改造,暫時停業
console.log(boss1.state) // 裝修中 

因而可知,對應用類型的變量僅僅經過變量賦值,沒法達到深拷貝的意圖,僅僅只是淺拷貝。blog

 

如何去作呢遞歸

如下簡單實現一個對純數據對象(JSON)的深拷貝

1.實現值類型的複製:

從上面咱們知道,值類型能夠簡單的經過變量賦值來實現深拷貝,因此先完成以下代碼:

function clone(item) {
  var type = typeof item, 
     baseTypes = ['boolean','number','string','undefined'],
     result;   
//使用typeof 能夠準確判斷出 boolean string number undefined   //null 使用全等方式進行判斷   if(baseTypes.indexOf(type) >= 0 || item === null){      result = item;   }
  return result; }

2.實現引用類型中數組的複製:

首先須要判斷是否爲數組,其次將數組進行遍歷,分別複製數組中的內容,暫時不考慮數組中元素包含引用類型

function clone(item) {
  var result;
  //判斷當前元素是否爲數組,至於爲何這麼判斷,不深刻了,有興趣本身百度吧~
  if(Object.prototype.toString.call(item) === "[object Array]"){
    result = [];
    //循環數組,將數組內容放到新數組中(未考慮數組中元素是否包含引用類型)
    item.forEach(function (i) {
      result.push(i);
    })
  }
  return result;
}

3.實現引用類型中對象的複製:

首先須要判斷是否爲對象,其次將對象進行遍歷,分別複製對象中的內容,暫時不考慮數組中元素包含引用類型

function clone1(item) {
  var result;
  //判斷當前元素是否爲對象,至於爲何這麼判斷,不深刻了,有興趣本身百度吧~
  if(Object.prototype.toString.call(item) === "[object Object]"){
    result = {};
    //遍歷對象,將對象中內容放到新對象中(未考慮對象中元素是否包含引用類型)
    for(var i in item){
      result[i] = item[i]; 
    }
  }
  return result;
}

4.將對象或數組中包含引用類型值的狀況考慮進去,一個簡單的遞歸調用,總體代碼以下

function clone(item) {
  var type = typeof item,
    baseTypes = ['boolean','number','string','undefined'],
    result;
  //使用typeof 能夠準確判斷出 boolean string number undefined
  //null 使用全等方式進行判斷
  if(baseTypes.indexOf(type) >= 0 || item === null){
    result = item;
  }else if(Object.prototype.toString.call(item) === "[object Array]"){ // 判斷是否爲數組
    result = [];
    //循環數組,將數組內容放到新數組中
    item.forEach(function (i) {
      result.push(clone(i));
    })
  }else if(Object.prototype.toString.call(item) === "[object Object]"){ // 判斷是否爲對象
    result = {};
    //遍歷對象,將對象中內容放到新對象中(未考慮對象中元素是否包含引用類型)
    for(var i in item){
      result[i] = clone(item[i]);
    }
  }else{
    result = item;
  }
    return result;
}

 

PS:還有沒有其餘簡便方法呢

咱們知道JSON,自己提供兩個方法 JSON.stringify() 和 JSON.parse(),提供了將JSON對象轉換爲JSON結構的字符串,以及將JSON結構的字符串換換爲JSON

so:簡便方法來了

function clone(item) {
  var jsonStr = JSON.stringify(item);
  return JSON.parse(jsonStr);
}
相關文章
相關標籤/搜索