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

分享

jquery.Data() 的實(shí)現(xiàn)方式

 昵稱18349714 2014-08-28

jQuery.data() 的作用是為普通對(duì)象或 DOM Element 附加(及獲取)數(shù)據(jù)。 
   下面將分三個(gè)部分分析其實(shí)現(xiàn)方式: 
   1. 用name和value為對(duì)象附加數(shù)據(jù);即傳入三個(gè)參數(shù),第一個(gè)參數(shù)為需要附加數(shù)據(jù)的對(duì)象,第二個(gè)參數(shù)為數(shù)據(jù)的名稱,第三個(gè)參數(shù)為數(shù)據(jù)的值。當(dāng)然,只是獲取值的話,也可以不傳入第三個(gè)參數(shù)。 
   2. 用另一個(gè)對(duì)象為對(duì)象附加數(shù)據(jù);即傳入兩個(gè)參數(shù),第一個(gè)參數(shù)為需要附加的數(shù)據(jù)對(duì)象(我們稱之為“obj”),第二個(gè)參數(shù)也是一個(gè)對(duì)象(我們稱之為“another”);“another”中包含的鍵值對(duì)將會(huì)被復(fù)制到 “obj” 的數(shù)據(jù)緩存(我們稱之為“cache”)中。 
   3. 為 DOM Element 附加數(shù)據(jù);DOM Element 也是一種 Object ,但 IE6、IE7 對(duì)直接附加在 DOM Element 上的對(duì)象的垃圾回收存在問(wèn)題;因此我們將這些數(shù)據(jù)存放在全局緩存(我們稱之為“globalCache”)中,即 “globalCache” 包含了多個(gè) DOM Element 的 “cache”,并在 DOM Element 上添加一個(gè)屬性,存放 “cache” 對(duì)應(yīng)的 uid 。 

用name和value為對(duì)象附加數(shù)據(jù)


   使用 jQuery.data() 為普通對(duì)象附加數(shù)據(jù)時(shí),其本質(zhì)是將一個(gè) “cache” 附加到了對(duì)象上,并使用了一個(gè)特殊的屬性名稱。 
   存放數(shù)據(jù)的 “cache” 也是一個(gè) object,我們?yōu)?“obj” 附加的數(shù)據(jù)實(shí)際上成為了 “cache” 的屬性。而 “cache” 又是 “obj” 的一個(gè)屬性,在 jQuery 1.6中,這個(gè)屬性的名稱是 “jQuery16”加上一個(gè)隨機(jī)數(shù)(如下面提到的 “jQuery16018518865841457738” )。 

   我們可以用下面的代碼來(lái)測(cè)試 jQuery.data() 的功能: 

  1. <script type="text/javascript" src="jquery.js"></script>  

  2. <script>  

  3. obj = {};  

  4. $.data(obj, 'name', 'value');  

  5. document.write("$.data(obj, 'name') = " + $.data(obj, 'name') + '<br />');  

  6.  

  7. for (var key in obj) {  

  8.    document.write("obj." + key + '.name = ' + obj[key].name);  

  9. }  

  10. </script>  


   顯示結(jié)果為:

  1. $.data(obj, 'name') = value  

  2. obj.jQuery16018518865841457738.name = value  


   在這段代碼中,我們首先在 “obj” 上附加了一個(gè)屬性(名稱為“name”,值為“value”),然后通過(guò) $.data(obj, 'name') 來(lái)獲取所附加的數(shù)據(jù)。為了深入了解其中的實(shí)現(xiàn)機(jī)制,我們有使用了一個(gè)循環(huán)來(lái)獲取 “obj” 的屬性,實(shí)際上是取出了在 “obj” 上附加的 “cache”對(duì)象。 

   可以看到,jQuery.data() 實(shí)際上為 “obj” 附加到了名為 “jQuery16018518865841457738” (這個(gè)名稱是隨機(jī)的)的對(duì)象,也就是 “cache” 上。用 jquery.data() 方式為對(duì)象附加的屬性實(shí)際上成為了這個(gè) “cache” 的屬性。 

   我們可以用下面的代碼實(shí)現(xiàn)類似的功能: 

  1. $ = function() {  

  2.    var expando = "jQuery" + ("1.6" + Math.random()).replace(/\D/g, '');  

  3.  

  4.    function getData(cache, name) {  

  5.        return cache[name];  

  6.    }  

  7.  

  8.    function setData(cache, name, value) {  

  9.        cache[name] = value;  

  10.    }  

  11.  

  12.    function getCache(obj) {  

  13.        obj[expando] = obj[expando] || {};  

  14.        return obj[expando];  

  15.    }  

  16.  

  17.    return {  

  18.        data : function(obj, name, value) {  

  19.            var cache = getCache(obj);  

  20.  

  21.            if (value === undefined) {  

  22.                return getData(cache, name);  

  23.            } else {  

  24.                setData(cache, name, value);  

  25.            }  

  26.        }  

  27.    }  

  28. }();  



   function 中的第一行代碼定義了 “expando” ,即 "jQuery1.6" 加上一個(gè)隨機(jī)數(shù)(0.xxxx),并將其中非數(shù)字的部分去掉;這種格式將在jQuery的其他地方用到,這里不做探討;只需要知道這是一個(gè)特殊的名稱,并且可以用于標(biāo)識(shí)不同的頁(yè)面(比如不同 iframe 中的 “expando” 就會(huì)有所不同)。 

   接下來(lái)定義了獲取數(shù)據(jù)的函數(shù) getData(), 即從 “cache” 中獲取一個(gè)屬性;實(shí)際上也就是返回 cache[name] 。 
   然后是 setData() 函數(shù),用于設(shè)置 “cache” 的屬性;實(shí)際上也就是設(shè)置 cache[name] 的值。 
   之后是 getCache() , 獲取 “obj” 上的 “cache”,即 obj[expando];如果 obj[expando] 為空,則進(jìn)行初始化。 
   最后公開(kāi)了 data 方法,先根據(jù)傳入的 “obj”,獲取附加在 “obj” 上的 “cache”; 當(dāng)傳入兩個(gè)參數(shù)時(shí),調(diào)用 getData()方法;當(dāng)傳入三個(gè)參數(shù)時(shí),則調(diào)用 setData() 方法。 


用另一個(gè)對(duì)象為對(duì)象附加數(shù)據(jù)


    除了以提供 name 和 value 的方式進(jìn)行賦值,我們還可以直接傳入另一個(gè)對(duì)象( “another” )作為參數(shù)。這種情況下,“another” 的屬性名稱和屬性值將被視為多個(gè)鍵值對(duì),從中提取的 “name” 和 “value” 都會(huì)被復(fù)制到目標(biāo)對(duì)象的緩存中。 

    功能測(cè)試代碼如下: 

  1. <script type="text/javascript" src="jquery.js"></script>  

  2. <script>  

  3. obj = {};  

  4. $.data(obj, {name1: 'value1', name2: 'value2'});  

  5.  

  6. document.write("$.data(obj, 'name1') = " + $.data(obj, 'name1')  + '<br />' );  

  7. document.write("$.data(obj, 'name2') = " + $.data(obj, 'name2') + '<br />');  

  8.  

  9. for (var key in obj) {  

  10.    document.write("obj." + key + '.name1 = ' + obj[key].name1 + '<br />');  

  11.    document.write("obj." + key + '.name2 = ' + obj[key].name2);  

  12. }  

  13. </script>  



   顯示結(jié)果如下: 

  1. $.data(obj, 'name1') = value1  

  2. $.data(obj, 'name2') = value2  

  3. obj.jQuery1600233050178663064.name1 = value1  

  4. obj.jQuery1600233050178663064.name2 = value2  



   上面的測(cè)試代碼中,我們先將一個(gè)帶有兩個(gè)鍵值對(duì)的 “another” 對(duì)象傳入,然后分別用 $.data(obj, 'name1') 和 $.data(obj, 'name2') 獲取附加的數(shù)據(jù);同樣,為了深入了解其中的機(jī)制,我們通過(guò)遍歷 “obj” 的方式取出了隱藏的 “cache” 對(duì)象,并獲得了 “cache” 對(duì)象的 “name1” 屬性和 “name2” 屬性的值。 

   可以看到,jQuery.data() 實(shí)際上為 “obj” 附加了名為 “obj.jQuery1600233050178663064” 的對(duì)象,也就是 “cache” 上。用 jquery.data() 方式傳入的鍵值對(duì)都被復(fù)制到了 “cache” 中。 

   我們可以用下面的代碼實(shí)現(xiàn)類似的功能: 

  1. $ = function() {  

  2.    // Other codes ...  

  3.  

  4.    function setDataWithObject(cache, another) {  

  5.        for (var name in another) {  

  6.            cache[name] = another[name];  

  7.        }  

  8.    }  

  9.  

  10.    // Other codes ...  

  11.  

  12.    return {  

  13.        data : function(obj, name, value) {  

  14.            var cache = getCache(obj);  

  15.  

  16.            if (name instanceof Object) {  

  17.                setDataWithObject(cache, name)  

  18.            } else if (value === undefined) {  

  19.                return getData(cache, name);  

  20.            } else {  

  21.                setData(cache, name, value);  

  22.            }  

  23.        }  

  24.    }  

  25. }();  



   這段代碼是在之前的代碼的基礎(chǔ)上進(jìn)行修改的。首先增加了內(nèi)部函數(shù) setDataWithObject() ,這個(gè)函數(shù)的實(shí)現(xiàn)是遍歷 “another” 的屬性,并復(fù)制到 “cache” 中。 
   然后,在對(duì)外開(kāi)放的 data 函數(shù)中,先判斷傳入的第二個(gè)參數(shù)的名稱,如果這個(gè)參數(shù)是一個(gè) Object 類型的實(shí)例,則調(diào)用 setDataWithObject() 方法。 


為 DOM Element 附加數(shù)據(jù)


   由于 DOM Element 也是一種 Object,因此之前的方式也可以為 DOM Element 賦值;但考慮到 IE6、IE7 中垃圾回收的問(wèn)題(不能有效回收 DOM Element 上附加的對(duì)象引用),jQuery采用了與普通對(duì)象有所不同的方式附加數(shù)據(jù)。 

   測(cè)試代碼如下: 

  1. <div id="div_test" />  

  2.  

  3. <script type="text/javascript" src="data.js"></script>  

  4. <script>  

  5. window.onload = function() {  

  6.    div = document.getElementById('div_test');  

  7.    $.data(div, 'name', 'value');  

  8.    document.write($.data(div, 'name'));  

  9. }  

  10. </script>  



   顯示結(jié)果如下: 

  1. value  



   測(cè)試代碼中,首先通過(guò) document.getElementById 方法獲取了一個(gè) DOM Element (當(dāng)然,也可以用 jQuery 的選擇器),然后在這個(gè) DOM Element 上附加了一個(gè)屬性,隨后就從 DOM Element 上取出了附加的屬性并輸出。 

   因?yàn)榭紤]到 IE6、IE7 對(duì) DOM Element 上的對(duì)象引用的垃圾回收存在問(wèn)題,我們不會(huì)直接在 DOM Element 上附加對(duì)象;而是使用全局cache,并在 DOM Element 上附加一個(gè) uid。 

   實(shí)現(xiàn)方式如下:

  1. $ = function() {  

  2.    var expando = "jQuery" + ("1.6" + Math.random()).replace(/\D/g, '');  

  3.    var globalCache = {};  

  4.    var uuid = 0;  

  5.  

  6.    // Other codes ...  

  7.  

  8.    function getCache(obj) {  

  9.        if (obj.nodeType) {  

  10.            var id = obj[expando] = obj[expando] || ++uuid;  

  11.            globalCache[id] = globalCache[id] || {};  

  12.            return globalCache[id];  

  13.        } else {  

  14.            obj[expando] = obj[expando] || {};  

  15.            return obj[expando];  

  16.        }  

  17.    }  

  18.  

  19.    // Other codes ...  

  20. }();  



   這段代碼與之前的代碼相比,增加了 globalCache 和 uuid,并修改了 getCache() 方法。 

   globalCache 對(duì)象用于存放附加到 DOM Element 上的 “cache”,可以視為 “cache” 的“容器”。uuid 表示 “cache” 對(duì)應(yīng)的唯一標(biāo)識(shí),是唯一且自增長(zhǎng)的。uuid 或被存放在 DOM Element 的 “expando” 屬性中。 
   getCache() 函數(shù)中增加了一個(gè)判斷,即 “obj” 具有 “nodeType” 屬性,就認(rèn)為這是一個(gè) DOM Element;這種情況下,就先取出附加在 “obj” 上的 id ,即 obj[expando] ;如果 obj[expando] 未定義,則先用 ++uuid 對(duì)其進(jìn)行初始化;取出 id 之后,就到 globalCache 中找到對(duì)應(yīng)的 “cache” ,即 globalCache[id], 并返回。 

   到此為止,jQuery.data() 函數(shù)的實(shí)現(xiàn)就介紹完了;但是,這里還有一個(gè)需要思考的問(wèn)題:為什不都統(tǒng)一用 “globalCache” 存儲(chǔ),而要將 “cache” 直接附加到普通對(duì)象上?我認(rèn)為這應(yīng)該是一種性能優(yōu)化的方式,畢竟少一個(gè)引用的層次,存取速度應(yīng)該會(huì)略快一些。 jQuery 中這刻意優(yōu)化的地方非常多,在許多原本可以統(tǒng)一處理的對(duì)方都進(jìn)行了特殊處理。但這在一定程度上,也造成了閱讀源碼的障礙。當(dāng)然這是作者(及其他代碼貢獻(xiàn)者)本身的編程哲學(xué),這里就不加評(píng)論了。



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(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)論公約

    類似文章 更多