javascript深拷貝是初學(xué)者甚至有經(jīng)驗(yàn)的開(kāi)發(fā)者,都會(huì)經(jīng)常遇到問(wèn)題,并不能很好的理解javascript的深拷貝。 深拷貝(deepClone)? 與深拷貝相對(duì)的就是淺拷貝,很多初學(xué)者在接觸這個(gè)感念的時(shí)候,是很懵逼的。 為啥要用深拷貝? 在很多情況下,我們都需要給變量賦值,給內(nèi)存地址賦予一個(gè)值,但是在賦值引用值類(lèi)型的時(shí)候,只是共享一個(gè)內(nèi)存區(qū)域,導(dǎo)致賦值的時(shí)候,還跟之前的值保持一直性。 看一個(gè)具體的例子
圖解: 這下就很好理解為什么引用值類(lèi)型數(shù)據(jù)相互影響問(wèn)題。 實(shí)現(xiàn) 實(shí)現(xiàn)一個(gè)深拷貝函數(shù),就不得不說(shuō)javascript的數(shù)值類(lèi)型。 判斷javascript類(lèi)型 javascript中有以下基本類(lèi)型
使用typeof是無(wú)法判斷function和array的,這里使用Object.prototype.toString方法。 默認(rèn)情況下,每個(gè)對(duì)象都會(huì)從Object上繼承到toString()方法,如果這個(gè)方法沒(méi)有被這個(gè)對(duì)象自身或者更接近的上層原型上的同名方法覆蓋(遮蔽),則調(diào)用該對(duì)象的toString()方法時(shí)會(huì)返回”[object type]”,這里的字符串type表示了一個(gè)對(duì)象類(lèi)型
實(shí)現(xiàn)deepClone 對(duì)于非引用值類(lèi)型的數(shù)值,直接賦值,而對(duì)于引用值類(lèi)型(object)還需要再次遍歷,遞歸賦值。
這里有個(gè)點(diǎn)大家要注意下,對(duì)于function類(lèi)型,博主這里是直接賦值的,還是共享一個(gè)內(nèi)存值。這是因?yàn)楹瘮?shù)更多的是完成某些功能,有個(gè)輸入值和返回值,而且對(duì)于上層業(yè)務(wù)而言更多的是完成業(yè)務(wù)功能,并不需要真正將函數(shù)深拷貝。 但是function類(lèi)型要怎么拷貝呢? 其實(shí)博主只想到了用new來(lái)操作一下,但是function就會(huì)執(zhí)行一遍,不敢想象會(huì)有什么執(zhí)行結(jié)果哦!o(╯□╰)o!其它暫時(shí)還沒(méi)有什么好的想法,歡迎大家指導(dǎo)哦! 到這里差不多也就實(shí)現(xiàn)完了深拷貝,又有人覺(jué)的怎么沒(méi)有實(shí)現(xiàn)淺拷貝呢? 淺拷貝? 對(duì)于淺拷貝而言,可以理解為只操作一個(gè)共同的內(nèi)存區(qū)域!這里會(huì)存在危險(xiǎn)!(。﹏。*) 。 如果直接操作這個(gè)共享的數(shù)據(jù),不做控制的話,會(huì)經(jīng)常出現(xiàn)數(shù)據(jù)異常,被其它部分更改。所以應(yīng)該不要直接操作數(shù)據(jù)源,給數(shù)據(jù)源封裝一些方法,來(lái)對(duì)數(shù)據(jù)來(lái)進(jìn)行CURD操作。 到這里估計(jì)就差不多了,但是作為一個(gè)前端,不僅僅考慮javascript本身,還得考慮到dom、瀏覽器等。 Element類(lèi)型 來(lái)看下面代碼,結(jié)果會(huì)返回啥呢?
答案是[object HTMLDivElement] 有時(shí)候保存了dom元素, 一不小心進(jìn)行深拷貝,上面的深拷貝函數(shù)就缺少了對(duì)Element元素的判斷。而判斷Element元素要使用instanceof來(lái)判斷。因?yàn)閷?duì)于不同的標(biāo)簽,tostring會(huì)返回對(duì)應(yīng)不同的標(biāo)簽的構(gòu)造函數(shù)。
其它方式? 1. jquery的實(shí)現(xiàn) 詳見(jiàn)https://github.com/jquery/jquery/blob/master/src/core.js 2. underscore的實(shí)現(xiàn) 詳見(jiàn)https://github.com/jashkenas/underscore/blob/master/underscore.js 3. lodash的實(shí)現(xiàn) 詳見(jiàn)https://github.com/lodash/lodash/blob/master/lodash.js 4. JSON實(shí)現(xiàn) 先通過(guò)JSON.stringify一下,然后再JSON.parse一下,就能實(shí)現(xiàn)深拷貝。但是數(shù)據(jù)類(lèi)型只支持基本數(shù)值類(lèi)型。
小結(jié) 這里大概總結(jié)了一下深拷貝,以及怎么實(shí)現(xiàn)一個(gè)深拷貝。在不同的場(chǎng)景下,要根據(jù)業(yè)務(wù)場(chǎng)景,判斷是否需要使用深拷貝。 參考文獻(xiàn) winter-JavaScript中的類(lèi)型 http://www.cnblogs.com/winter-cn/archive/2009/12/07/1618281.html 專(zhuān)欄作者簡(jiǎn)介 ( 點(diǎn)擊 → 加入專(zhuān)欄作者 ) |
|
來(lái)自: melon1024 > 《編程語(yǔ)言》