日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Javascript 深拷貝

 melon1024 2016-08-28


作者:伯樂(lè)在線專(zhuān)欄作者 - 前端-小強(qiáng)

鏈接:http://web./87627/

點(diǎn)擊 → 了解如何加入專(zhuān)欄作者


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è)具體的例子


// 給test賦值了一個(gè)對(duì)象

var test = {

a: 'a',

b: 'b'

};

 

// 將test賦值給test2

// 此時(shí)test和test2是共享了同一塊內(nèi)存對(duì)象,這也就是淺拷貝

var test2 = test;

 

test2.a = 'a2';

 

test.a === 'a2'// 為true


圖解:



這下就很好理解為什么引用值類(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)型


類(lèi)型描述
undefinedundefined類(lèi)型只有一個(gè)值undefined,它是變量未被賦值時(shí)的值
nullnull類(lèi)型也只有一個(gè)值null, 它是一個(gè)空的對(duì)象引用
BooleanBoolean有兩種取值true和false
String它表示文本信息
Number它表示數(shù)字信息
Object它是一系列屬性的無(wú)序集合, 包括函數(shù)Function和數(shù)組Array


使用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)型


function type(obj) {

var toString = Object.prototype.toString;

var map = {

    '[object Boolean]'  : 'boolean',

    '[object Number]'   : 'number',

    '[object String]'   : 'string',

    '[object Function]' : 'function',

    '[object Array]'    : 'array',

    '[object Date]'     : 'date',

    '[object RegExp]'   : 'regExp',

    '[object Undefined]': 'undefined',

    '[object Null]'     : 'null',

    '[object Object]'   : 'object'

};

return map[toString.call(obj)];

}


 實(shí)現(xiàn)deepClone


對(duì)于非引用值類(lèi)型的數(shù)值,直接賦值,而對(duì)于引用值類(lèi)型(object)還需要再次遍歷,遞歸賦值。


function deepClone(data) {

var t = type(data), o, i, ni;

if(t === 'array') {

    o = [];

}else if( t === 'object') {

    o = {};

}else {

    return data;

}

if(t === 'array') {

    for (i = 0, ni = data.length; i < ni; i ) {

        o.push(deepClone(data[i]));

    }

    return o;

}else if( t === 'object') {

    for( i in data) {

        o[i] = deepClone(data[i]);

    }

    return o;

}

}


這里有個(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.prototype.toString.call(document.getElementsByTagName('div')[0])


答案是[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ù)。


function type(obj) {

var toString = Object.prototype.toString;

var map = {

    '[object Boolean]'  : 'boolean',

    '[object Number]'   : 'number',

    '[object String]'   : 'string',

    '[object Function]' : 'function',

    '[object Array]'    : 'array',

    '[object Date]'     : 'date',

    '[object RegExp]'   : 'regExp',

    '[object Undefined]': 'undefined',

    '[object Null]'     : 'null',

    '[object Object]'   : 'object'

};

if(obj instanceof Element) {

        return 'element';

}

return map[toString.call(obj)];

}


其它方式?


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)型。


var obj = {

    a: 'a',    

    b: function(){console.log('b')}

}

 

//在JSON.stringify的時(shí)候就會(huì)把function給過(guò)濾了。

 

JSON.stringify(obj)// '{'a':'a'}'


小結(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)欄作者 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多