對一個對象或者數組這種引用類型的值進行復制能夠分爲淺複製和深複製,好比這樣的一個對象數組
let obj={ a:1, b:{ a:1, b:2 }, c:3 }
很明顯這個對象是存在兩層的,obj[b]不是基本類型值,而是另外一個對象。若是使用淺複製去拷貝這個對象的話,那麼拷貝出來新的對象的b屬性的值是原來對象b屬性的引用地址,也就是說,若是改變源對象的b屬性,新的對象也會受到影響,由於咱們只使用淺複製拷貝了一層。函數
上面講的就是淺複製,在實際應用中存在很嚴重的問題。因此咱們通常複製對象都是用深複製,深複製不是簡單的複製一層,而是遍歷整個對象,一直到獲取到的值不是引用類型,而是基本類型的時候才進行復制,這樣就使得新的對象跟原來的對象徹底是兩個不一樣的對象了。code
下面是我寫的一個簡單的深複製函數對象
let obj={ a:1, b:{ a:1, b:2 }, c:3 } function deepClone(object){ let obj=new Object(); if(object instanceof Object){ // 說明是對象 for(let attr in object){ if(object.hasOwnProperty(attr)){ // 過濾基本類型值 if(typeof object[attr]!='object'||object[attr]==null){ obj[attr]=object[attr]; }else{ obj[attr]=deepClone(object[attr]); } } } } return obj; } let obj2=deepClone(obj); obj.b=1; console.log(obj,obj2);
注意,這個函數是存在問題的,由於這個函數只能處理純對象類型,也就是說屬性中包含數組的對象該方法是沒法處理的。get
下面這裏有一個方法是stackoverflow
上的答案,兼容了數組與對象的string
function clone(obj) { var copy; // Handle the 3 simple types, and null or undefined if (null == obj || "object" != typeof obj) return obj; // Handle Date if (obj instanceof Date) { copy = new Date(); copy.setTime(obj.getTime()); return copy; } // Handle Array if (obj instanceof Array) { copy = []; for (var i = 0, len = obj.length; i < len; i++) { copy[i] = clone(obj[i]); } return copy; } // Handle Object if (obj instanceof Object) { copy = {}; for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]); } return copy; } throw new Error("Unable to copy obj! Its type isn't supported."); }
還有一種比較抖機靈的作法就是io
var cloneOfA = JSON.parse(JSON.stringify(a));
這種作法也是能夠實現深複製,可是因爲JSON.stringify()
方法在遇到undefined
值時會省略對應的屬性,因此這個方法不太推薦使用,存在問題。console
基於jQ的作法是這樣的function
var copiedObject = jQuery.extend({}, originalObject) // shallow copy淺複製 var copiedObject = jQuery.extend(true, {}, originalObject) // deep copy深複製