国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

深入理解jQuery.data() 的實現(xiàn)方式

2019-11-19 18:45:04
字體:
供稿:網(wǎng)友

jQuery.data() 的作用是為普通對象或 DOM Element 附加(及獲取)數(shù)據(jù)。 

下面將分三個部分分析其實現(xiàn)方式: 

1. 用name和value為對象附加數(shù)據(jù);即傳入三個參數(shù),第一個參數(shù)為需要附加數(shù)據(jù)的對象,第二個參數(shù)為數(shù)據(jù)的名稱,第三個參數(shù)為數(shù)據(jù)的值。當(dāng)然,只是獲取值的話,也可以不傳入第三個參數(shù)。 

2. 用另一個對象為對象附加數(shù)據(jù);即傳入兩個參數(shù),第一個參數(shù)為需要附加的數(shù)據(jù)對象(我們稱之為“obj”),第二個參數(shù)也是一個對象(我們稱之為“another”);“another”中包含的鍵值對將會被復(fù)制到 “obj” 的數(shù)據(jù)緩存(我們稱之為“cache”)中。 

3. 為 DOM Element 附加數(shù)據(jù);DOM Element 也是一種 Object ,但 IE6、IE7 對直接附加在 DOM Element 上的對象的垃圾回收存在問題;因此我們將這些數(shù)據(jù)存放在全局緩存(我們稱之為“globalCache”)中,即 “globalCache” 包含了多個 DOM Element 的 “cache”,并在 DOM Element 上添加一個屬性,存放 “cache” 對應(yīng)的 uid 。

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

使用 jQuery.data() 為普通對象附加數(shù)據(jù)時,其本質(zhì)是將一個 “cache” 附加到了對象上,并使用了一個特殊的屬性名稱。 

存放數(shù)據(jù)的 “cache” 也是一個 object,我們?yōu)?“obj” 附加的數(shù)據(jù)實際上成為了 “cache” 的屬性。而 “cache” 又是 “obj” 的一個屬性,在 jQuery 1.6中,這個屬性的名稱是 “jQuery16”加上一個隨機數(shù)(如下面提到的 “jQuery16018518865841457738” )。

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

<script type="text/javascript" src="jqueryjs"></script> <script> obj = {}; $data(obj, 'name', 'value'); documentwrite("$data(obj, 'name') = " + $data(obj, 'name') + '<br />');  for (var key in obj) {  documentwrite("obj" + key + 'name = ' + obj[key]name); } </script> 

顯示結(jié)果為:

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

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

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

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

$ = function() {  var expando = "jQuery" + ("6" + Mathrandom())replace(//D/g, '');   function getData(cache, name) {  return cache[name];  }   function setData(cache, name, value) {  cache[name] = value;  }   function getCache(obj) {  obj[expando] = obj[expando] || {};  return obj[expando];  }   return {  data : function(obj, name, value) {   var cache = getCache(obj);    if (value === undefined) {   return getData(cache, name);   } else {   setData(cache, name, value);   }  }  } }(); 

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

接下來定義了獲取數(shù)據(jù)的函數(shù) getData(), 即從 “cache” 中獲取一個屬性;實際上也就是返回 cache[name] 。 

然后是 setData() 函數(shù),用于設(shè)置 “cache” 的屬性;實際上也就是設(shè)置 cache[name] 的值。 

之后是 getCache() , 獲取 “obj” 上的 “cache”,即 obj[expando];如果 obj[expando] 為空,則進行初始化。 

最后公開了 data 方法,先根據(jù)傳入的 “obj”,獲取附加在 “obj” 上的 “cache”; 當(dāng)傳入兩個參數(shù)時,調(diào)用 getData()方法;當(dāng)傳入三個參數(shù)時,則調(diào)用 setData() 方法。

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

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

功能測試代碼如下:

<script type="text/javascript" src="jqueryjs"></script> <script> obj = {}; $data(obj, {name1: 'value1', name2: 'value2'});  documentwrite("$data(obj, 'name1') = " + $data(obj, 'name1') + '<br />' ); documentwrite("$data(obj, 'name2') = " + $data(obj, 'name2') + '<br />');  for (var key in obj) {  documentwrite("obj" + key + 'name1 = ' + obj[key]name1 + '<br />');  documentwrite("obj" + key + 'name2 = ' + obj[key]name2); } </script> 

顯示結(jié)果如下:

$.data(obj, 'name1') = value1 $.data(obj, 'name2') = value2 obj.jQuery1600233050178663064.name1 = value1 obj.jQuery1600233050178663064.name2 = value2 

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

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

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

$ = function() {  // Other codes   function setDataWithObject(cache, another) {  for (var name in another) {   cache[name] = another[name];  }  }   // Other codes   return {  data : function(obj, name, value) {   var cache = getCache(obj);    if (name instanceof Object) {   setDataWithObject(cache, name)   } else if (value === undefined) {   return getData(cache, name);   } else {   setData(cache, name, value);   }  }  } }(); 

這段代碼是在之前的代碼的基礎(chǔ)上進行修改的。首先增加了內(nèi)部函數(shù) setDataWithObject() ,這個函數(shù)的實現(xiàn)是遍歷 “another” 的屬性,并復(fù)制到 “cache” 中。 

然后,在對外開放的 data 函數(shù)中,先判斷傳入的第二個參數(shù)的名稱,如果這個參數(shù)是一個 Object 類型的實例,則調(diào)用 setDataWithObject() 方法。

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

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

測試代碼如下:

<script type="text/javascript" src="datajs"></script> <script> windowonload = function() {  div = documentgetElementById('div_test');  $data(div, 'name', 'value');  documentwrite($data(div, 'name')); } </script> 

顯示結(jié)果如下:

value 

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

因為考慮到 IE6、IE7 對 DOM Element 上的對象引用的垃圾回收存在問題,我們不會直接在 DOM Element 上附加對象;而是使用全局cache,并在 DOM Element 上附加一個 uid。

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

$ = function() {  var expando = "jQuery" + ("6" + Mathrandom())replace(//D/g, '');  var globalCache = {};  var uuid = 0;   // Other codes   function getCache(obj) {  if (objnodeType) {   var id = obj[expando] = obj[expando] || ++uuid;   globalCache[id] = globalCache[id] || {};   return globalCache[id];  } else {   obj[expando] = obj[expando] || {};   return obj[expando];  }  }   // Other codes }(); 

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

globalCache 對象用于存放附加到 DOM Element 上的 “cache”,可以視為 “cache” 的“容器”。uuid 表示 “cache” 對應(yīng)的唯一標(biāo)識,是唯一且自增長的。uuid 或被存放在 DOM Element 的 “expando” 屬性中。 

getCache() 函數(shù)中增加了一個判斷,即 “obj” 具有 “nodeType” 屬性,就認(rèn)為這是一個 DOM Element;這種情況下,就先取出附加在 “obj” 上的 id ,即 obj[expando] ;如果 obj[expando] 未定義,則先用 ++uuid 對其進行初始化;取出 id 之后,就到 globalCache 中找到對應(yīng)的 “cache” ,即 globalCache[id], 并返回。

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 抚远县| 那坡县| 河东区| 民勤县| 太白县| 松桃| 盐边县| 西畴县| 色达县| 鄯善县| 扎赉特旗| 宁安市| 和静县| 连城县| 府谷县| 花莲市| 晋城| 华池县| 东乌珠穆沁旗| 安陆市| 南雄市| 灌阳县| 新巴尔虎右旗| 曲水县| 彭州市| 石泉县| 改则县| 张北县| 磐安县| 鹤山市| 共和县| 石渠县| 无棣县| 徐水县| 托里县| 桑植县| 宝鸡市| 息烽县| 灵台县| 北碚区| 武城县|