摘要:在聊以下簡稱深度克隆之前,我們先來了解一下中對象的組成。克隆或者拷貝分為種淺度克隆深度克隆。淺度克隆基本類型為值傳遞,對象仍為引用傳遞。
該文轉載自http://www.cnblogs.com/zichi/p/4568150.html,有部分修改。
在聊JavaScript(以下簡稱js)深度克隆之前,我們先來了解一下js中對象的組成。
在 js 中一切實例皆是對象,具體分為 原始類型 和 合成類型 :
原始類型 對象指的是 Undefined 、 Null 、Boolean 、Number 和 String ,按值傳遞。
合成類型 對象指的是 array 、 object 以及 function ,按址傳遞,傳遞的時候是內存中的地址。
克隆或者拷貝分為2種: 淺度克隆 、 深度克隆 。
淺度克隆 :基本類型為值傳遞,對象仍為引用傳遞。
深度克隆 :所有元素或屬性均完全克隆,并于原引用類型完全獨立,即,在后面修改對象的屬性的時候,原對象不會被修改。
又或許你剛聽說“深度克隆”這個詞,簡單來說,就是說有個變量a,a的值是個對象(包括基本數據類型),現在你要創建一個變量b,使得它擁有跟a一樣的方法和屬性等等。但是a和b之間不能相互影響,即a的值的改變不影響b值的變化。直接賦值可好?
var a = 1; var b = a; a = 10; console.log(b); // 1 var a = "hello"; var b = a; a = "world"; console.log(b); // hello var a = true; var b = a; a = false; console.log(b); // true
實踐證明某些 JavaScript 的原始數據類型,如果要克隆直接賦值即可。
關于 function 的深度復制:查閱了一些資料, function 的深度復制似乎和原始數據類型的深度復制一樣。
var a = function () { console.log(1); }; var b = a; a = function () { console.log(2); }; b(); // 1
本來我也是這么認為的,直到文章下出現了評論。思考后我覺得 function 和普通的對象一樣,只是我們在平常應用中習慣了整體的重新賦值,導致它在深度復制中的表現和原始類型一致:
var a = function () { console.log(1); }; a.tmp = 10; var b = a; a.tmp = 20; console.log(b.tmp); // 20
于是乎對于 function 類型的深度克隆,直接賦值似乎并不應該是一種最好的方法(盡管實際應用中足矣)。
但是對象呢?
var a = [0,1,2,3]; var b = a; a.push(4); console.log(b); // [0, 1, 2, 3, 4]
顯然與預期不符,為什么會這樣?因為原始數據類型儲存的是對象的實際數據,而對象類型存儲的是對象的引用地址。上面的例子呢也就是說a和b對象引用了同一個地址,無論改變a還是改變b,其實根本操作是一樣的,都是對那塊空間地址中的值的改變。
于是我們知道了,對于基本的對象來說,不能只能用 “ = ” 賦值,思索后寫下如下代碼:
// 判斷arr是否為一個數組,返回一個bool值 function isArray (arr) { return Object.prototype.toString.call(arr) === "[object Array]"; } // 深度克隆 function deepClone (obj) { if(typeof obj !== "object" && typeof obj !== "function") { return obj; //原始類型直接返回 } var o = isArray(obj) ? [] : {}; for(i in obj) { if(obj.hasOwnProperty(i)){ o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; } } return o; }
注意代碼中判斷數組的時候用的不是 obj instanceof Array ,這是因為該方法存在一些小問題,詳情見 http://www.nowamagic.net/librarys/veda/detail/1250
用一些代碼來測試下:
// 測試用例: var srcObj = { a: 1, b: { b1: ["hello", "hi"], b2: "JavaScript" } }; var abObj = srcObj; var tarObj = cloneObject(srcObj); srcObj.a = 2; srcObj.b.b1[0] = "Hello"; console.log(abObj.a); console.log(abObj.b.b1[0]); console.log(tarObj.a); // 1 console.log(tarObj.b.b1[0]); // "hello"
似乎可以解決一般的對象(包括 Array )的深度克隆了,或許這兒會有疑問,new String(..) 這類的也是對象啊,可是這樣寫你克隆不了啊…但是樓主覺得深度克隆的考點不在這里,可能在于:
原始數據類型的直接賦值
function的exception
對象的深度克隆中Array類型的判斷
克隆函數的遞歸調用
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78783.html
摘要:對象詳解對象深度剖析,深度理解對象這算是醞釀很久的一篇文章了。用空構造函數設置類名每個對象都共享相同屬性每個對象共享一個方法版本,省內存。 js對象詳解(JavaScript對象深度剖析,深度理解js對象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個基于對象(沒有類的概念)的語言,從入門到精通到放棄一直會被對象這個問題圍繞。 平時發的文章基本都是開發中遇到的問題和對...
摘要:如何深度克隆一個對象在我們日常工作中經常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數的配置相信很多人會想到用和方法去克隆一個對象,這個可以明確告訴大家這些都是些不靠譜的淺度克隆。 如何深度克隆一個對象 在我們日常工作中經常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數的配置 相信很多人會想到用 Object.assign, JSON.stringify 和...
摘要:它接受任意數量的源對象,枚舉它們的所有屬性并分配給。所以現在怎么辦有幾種方法可以創建一個對象的深拷貝。為了防止發生任何意外,請使用而不是。我想測量哪種方法是最高性能的。圖表以下是,和中不同技術的性能。 原文:Deep-copying in JavaScript - DasSur.ma 如何在 JavaScript 中拷貝一個對象?對于這個很簡單的問題,但是答案卻不簡單。 引用傳值 在...
閱讀 2432·2021-10-09 09:59
閱讀 2183·2021-09-23 11:30
閱讀 2598·2019-08-30 15:56
閱讀 1150·2019-08-30 14:00
閱讀 2944·2019-08-29 12:37
閱讀 1260·2019-08-28 18:16
閱讀 1661·2019-08-27 10:56
閱讀 1028·2019-08-26 17:23