摘要:在聊以下簡稱深度克隆之前,我們先來了解一下中對象的組成??寺』蛘呖截惙譃榉N淺度克隆深度克隆。淺度克隆基本類型為值傳遞,對象仍為引用傳遞。
該文轉(zhuǎn)載自http://www.cnblogs.com/zichi/p/4568150.html,有部分修改。
在聊JavaScript(以下簡稱js)深度克隆之前,我們先來了解一下js中對象的組成。
在 js 中一切實例皆是對象,具體分為 原始類型 和 合成類型 :
原始類型 對象指的是 Undefined 、 Null 、Boolean 、Number 和 String ,按值傳遞。
合成類型 對象指的是 array 、 object 以及 function ,按址傳遞,傳遞的時候是內(nèi)存中的地址。
克隆或者拷貝分為2種: 淺度克隆 、 深度克隆 。
淺度克隆 :基本類型為值傳遞,對象仍為引用傳遞。
深度克隆 :所有元素或?qū)傩跃耆寺。⒂谠妙愋屯耆毩?,即,在后面修改對象的屬性的時候,原對象不會被修改。
又或許你剛聽說“深度克隆”這個詞,簡單來說,就是說有個變量a,a的值是個對象(包括基本數(shù)據(jù)類型),現(xiàn)在你要創(chuàng)建一個變量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 的原始數(shù)據(jù)類型,如果要克隆直接賦值即可。
關(guān)于 function 的深度復(fù)制:查閱了一些資料, function 的深度復(fù)制似乎和原始數(shù)據(jù)類型的深度復(fù)制一樣。
var a = function () { console.log(1); }; var b = a; a = function () { console.log(2); }; b(); // 1
本來我也是這么認為的,直到文章下出現(xiàn)了評論。思考后我覺得 function 和普通的對象一樣,只是我們在平常應(yīng)用中習慣了整體的重新賦值,導致它在深度復(fù)制中的表現(xiàn)和原始類型一致:
var a = function () { console.log(1); }; a.tmp = 10; var b = a; a.tmp = 20; console.log(b.tmp); // 20
于是乎對于 function 類型的深度克隆,直接賦值似乎并不應(yīng)該是一種最好的方法(盡管實際應(yīng)用中足矣)。
但是對象呢?
var a = [0,1,2,3]; var b = a; a.push(4); console.log(b); // [0, 1, 2, 3, 4]
顯然與預(yù)期不符,為什么會這樣?因為原始數(shù)據(jù)類型儲存的是對象的實際數(shù)據(jù),而對象類型存儲的是對象的引用地址。上面的例子呢也就是說a和b對象引用了同一個地址,無論改變a還是改變b,其實根本操作是一樣的,都是對那塊空間地址中的值的改變。
于是我們知道了,對于基本的對象來說,不能只能用 “ = ” 賦值,思索后寫下如下代碼:
// 判斷arr是否為一個數(shù)組,返回一個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; }
注意代碼中判斷數(shù)組的時候用的不是 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(..) 這類的也是對象啊,可是這樣寫你克隆不了啊…但是樓主覺得深度克隆的考點不在這里,可能在于:
原始數(shù)據(jù)類型的直接賦值
function的exception
對象的深度克隆中Array類型的判斷
克隆函數(shù)的遞歸調(diào)用
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/78783.html
摘要:對象詳解對象深度剖析,深度理解對象這算是醞釀很久的一篇文章了。用空構(gòu)造函數(shù)設(shè)置類名每個對象都共享相同屬性每個對象共享一個方法版本,省內(nèi)存。 js對象詳解(JavaScript對象深度剖析,深度理解js對象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個基于對象(沒有類的概念)的語言,從入門到精通到放棄一直會被對象這個問題圍繞。 平時發(fā)的文章基本都是開發(fā)中遇到的問題和對...
摘要:如何深度克隆一個對象在我們?nèi)粘9ぷ髦薪?jīng)常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數(shù)的配置相信很多人會想到用和方法去克隆一個對象,這個可以明確告訴大家這些都是些不靠譜的淺度克隆。 如何深度克隆一個對象 在我們?nèi)粘9ぷ髦薪?jīng)常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數(shù)的配置 相信很多人會想到用 Object.assign, JSON.stringify 和...
摘要:它接受任意數(shù)量的源對象,枚舉它們的所有屬性并分配給。所以現(xiàn)在怎么辦有幾種方法可以創(chuàng)建一個對象的深拷貝。為了防止發(fā)生任何意外,請使用而不是。我想測量哪種方法是最高性能的。圖表以下是,和中不同技術(shù)的性能。 原文:Deep-copying in JavaScript - DasSur.ma 如何在 JavaScript 中拷貝一個對象?對于這個很簡單的問題,但是答案卻不簡單。 引用傳值 在...
閱讀 2491·2021-10-09 09:59
閱讀 2271·2021-09-23 11:30
閱讀 2662·2019-08-30 15:56
閱讀 1206·2019-08-30 14:00
閱讀 3004·2019-08-29 12:37
閱讀 1328·2019-08-28 18:16
閱讀 1713·2019-08-27 10:56
閱讀 1085·2019-08-26 17:23