也不知道從什麼時候開始,前端圈冒出了個新詞:物件深度克隆。看起來好像很高大上的樣子,實際上並不新鮮,在我們的實際專案開發中,你可能早已用到,只不過由於漢字的博大精深,有些原本很簡單的事物被一些看似專業的詞彙稍加修飾,就變得神秘起來了。
首先為什麼要將一個物件進行深克隆?請容許我進行一個猜測:你有時一定會認為js的內建物件document太長,那麼你可能會這樣做:
上述程式碼對document.getElementById進行了簡化,同時在原document物件中也增加了一個by的成員方法,你可以透過document.hasOwnProperty('by')傳回的狀態值來驗證你的判斷。再看下面一個例子。
由此可見,將一個物件透過簡單的傳遞給一個新的變數時,僅僅只是為該物件增添了一個別名。這意味著,透過對該別名的操作,原有物件鍵值會改變。但問題在於,有時我們希望newPerson完全獨立於person,彼此之間不存在同步關係,那麼就需要產生一個副本,請看例子:
//測試
var obj = {a: 0, b: 1, c: 2};
var arr = [0, 1, 2];
//執行深度複製
var newobj = cloneObj(obj);
var newarr = cloneObj(arr);
//將複製後的新物件進行成員刪除
delete newobj.a;
newarr.splice(0,1);
console.log(obj, arr, newobj, newarr);
//結果: {a: 0, b: 1, c: 2}, [0, 1, 2], {b: 1, c: 2}, [1, 2];
這便是所謂的物件克隆。不過有幾處要解釋一下。程式碼中的JSON物件及其成員方法stringify和parse屬於ECMAScript5規範,它們分別負責將一個物件(包括陣列物件)轉換成字串,和還原,從而實現物件的深拷貝。那麼對於低階瀏覽器(如IE),拷貝數組的話,可以用newobj.concat(obj),而普通對象,就索性枚舉賦值好了。