前言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); }