jQuery對(duì)象數(shù)據(jù)緩存Cache原理及jQuery.data方法區(qū)別介紹
更新時(shí)間:2013年04月07日 15:54:08 作者:
jQuery.data(..)來(lái)實(shí)現(xiàn)數(shù)據(jù)緩存,但有兩個(gè)用戶經(jīng)常使用的data([key],[value])和jQuery.data(element,[key],[value]),接下來(lái)為大家介紹下他們的區(qū)別,感興趣的朋友可以參考下哈
網(wǎng)上有很多教你怎么使用jQuery.data(..)來(lái)實(shí)現(xiàn)數(shù)據(jù)緩存,但有兩個(gè)用戶經(jīng)常使用的data([key],[value])和jQuery.data(element,[key],[value])幾乎沒(méi)有什么文章說(shuō)清楚它們兩的區(qū)別,所以我用到了,研究下分享給大家。
$("").data([key],[value])與jQuery.data(element,[key],[value])的區(qū)別
這兩個(gè)函數(shù)都是用來(lái)在元素上存放數(shù)據(jù)也就平時(shí)所說(shuō)的數(shù)據(jù)緩存,都返回jQuery對(duì)象,當(dāng)時(shí)我分別在使用它倆的時(shí)候真的嚇我一跳,區(qū)別可大了,真是不用不知道,一用嚇一跳??蠢酉劝桑笤俑鶕?jù)源代碼分析。
Js代碼:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var e=$("div");//定義了兩jquery對(duì)象
var w=$("div");//e是不等于w的。
//首先使用data([key],[value])用法。
$(e).data("a","aaaa");//分別在e和w上保存Key一樣的數(shù)據(jù),
$(w).data("a","wwww");// 看它是否會(huì)覆蓋前面的,雖然是保存在不同對(duì)象上。
alert($(e).data("a"));//你猜到答案了嗎,里輸出是wwww;是不是有點(diǎn)意外?
alert(e===w)//false
alert($(w).data("a"));//這里也是wwww;
//使用jQuery.data(element,[key],[value])來(lái)存放數(shù)據(jù)。
$.data(e,"b","cccc");//分別在e和w上保存Key一樣的數(shù)據(jù),
$.data(w,"b","dddd");// 看它是否會(huì)覆蓋前面的,雖然是保存在不同對(duì)象上。
alert($.data(e,"b"));//應(yīng)該你能猜答案吧,輸出cccc
alert($.data(w,"b"));//這輸出dddd
});
});
</script>
看了上面的例子是不是發(fā)現(xiàn)data([key],[value])與jQuery.data(element,[key],[value])兩個(gè)根本就不一樣了對(duì)吧?它們之間到底有沒(méi)有關(guān)系呢。怎么data([key],[value])會(huì)覆蓋前面key相同的值呢?
而jQuery.data(element,[key],[value])只要是綁定到不同的對(duì)象上都不會(huì)造成覆蓋。是這樣嗎?那來(lái)研究下它們的源代碼吧。
先看jQuery.data(element,[key],[value])源代碼。
Js代碼:
jQuery.extend({
cache: {},
// Please use with caution
uuid: 0,
// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
....
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
// 是否可以附加數(shù)據(jù),不可以則直接返回
if ( !jQuery.acceptData( elem ) ) {
return;
}
var privateCache, thisCache, ret,
//jQuery.expando這是一個(gè)唯一的字符串,是這介jquery對(duì)象產(chǎn)生的時(shí)候就生成了。
internalKey = jQuery.expando,
getByName = typeof name === "string",
// 必須區(qū)分處理DOM元素和JS對(duì)象,因?yàn)镮E6-7不能垃圾回收對(duì)象跨DOM對(duì)象和JS對(duì)象進(jìn)行的引用屬性
isNode = elem.nodeType,
// 如果是DOM元素,則使用全局的jQuery.cache
// 如果是JS對(duì)象,則直接附加到對(duì)象上
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
isEvents = name === "events";
// 避免做更多的不必要工作,當(dāng)嘗試在一個(gè)沒(méi)有任何數(shù)據(jù)的對(duì)象上獲取數(shù)據(jù)時(shí)
// 對(duì)象沒(méi)有任何數(shù)據(jù),直接返回
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// id不存在的話就生成一個(gè)
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
// 如果是DOM元素則在元素上產(chǎn)生唯一的ID 并且以jQuery.expando
//為屬性值為id保存在elem元素上,以便以后再根據(jù)jQuery.expando來(lái)查找ID。
elem[ internalKey ] = id = ++jQuery.uuid;
} else {
// JS對(duì)象則直接使用jQuery.expando,既然是直接附加到對(duì)象上,又何必要id呢?
// 避免與其他屬性沖突!
id = internalKey;
}
}
//// 當(dāng)我們?cè)囍L問(wèn)一個(gè)鍵是否含有值的時(shí)候,如果不存在jQuery.cache[id]值,
// 初始化jQuery.cache[id]值 為一個(gè)空對(duì)象{}
if ( !cache[ id ] ) {
cache[ id ] = {};
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
// data是接收對(duì)象和函數(shù),淺拷貝
if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) {
cache[ id ] = jQuery.extend( cache[ id ], name );
} else {
cache[ id ].data = jQuery.extend( cache[ id ].data, name );
}
}
/ 存儲(chǔ)對(duì)象,存放了所有數(shù)據(jù)的映射對(duì)象
privateCache = thisCache = cache[ id ];
// jQuery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data.
// jQuery內(nèi)部數(shù)據(jù)存在一個(gè)獨(dú)立的對(duì)象(thisCache.data==thisCache[ internalKey ])
//上,為了避免內(nèi)部數(shù)據(jù)和用戶定義數(shù)據(jù)沖突
if ( !pvt ) {
// 存放私有數(shù)據(jù)的對(duì)象不存在,則創(chuàng)建一個(gè){}
if ( !thisCache.data ) {
thisCache.data = {};
}
// 使用私有數(shù)據(jù)對(duì)象替換thisCache
thisCache = thisCache.data;
}
// 如果data不是undefined,表示傳入了data參數(shù),則存儲(chǔ)data到name屬性上
if ( data !== undefined ) {
// jQuery.camelCase( name )作用是如果傳入的是object/function,不做轉(zhuǎn)換,
//只有傳入的name是字符串才會(huì)轉(zhuǎn)換。所以最終保存下來(lái)的是key/value對(duì);
thisCache[ jQuery.camelCase( name ) ] = data;
}
//從這以后下面的代碼都是處理data: function( elem, name)data為空,求返回值data的情況了。
if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}
// 如果name是字符串,則返回data
// 如果不是,則返回整個(gè)存儲(chǔ)對(duì)象
if ( getByName ) {
// First Try to find as-is property data
ret = thisCache[ name ];
// Test for null|undefined property data
if ( ret == null ) {
// Try to find the camelCased property
ret = thisCache[ jQuery.camelCase( name ) ];
}
} else {
ret = thisCache;
}
return ret;
},
............
});
請(qǐng)看圖
看jQuery.data(element,[key],[value])源代碼后可以知道,每一個(gè)element都會(huì)有自己的一個(gè){key:value}對(duì)象保存著數(shù)據(jù),所以新建的對(duì)象就算有key相同它也不會(huì)覆蓋原來(lái)存在的對(duì)象key所對(duì)應(yīng)的value,因?yàn)樾聦?duì)象保存是是在另一個(gè){key:value}對(duì)象中。
接下來(lái)要分析data([key],[value])源代碼使用到了each(callback),在分析它之前先看下each(callback)用法和源代碼。
Js代碼:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var i=0;
$("#abc3").each(function() {
alert(++i);//只輸出1;因?yàn)橹挥幸粋€(gè)<div id="abc3">
});
alert("----");
var j=0;
$("div").each(function() {
alert(++j);//分別輸出1,2,3;因?yàn)橛腥齻€(gè)<div>所以循環(huán)三遍
});
});
});
</script>
現(xiàn)在來(lái)看each方法的具體實(shí)現(xiàn)如下:
jQuery.fn = jQuery.prototype = {
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
}
可以看到它返回的是全局的each方法,并且將自身jQuery對(duì)象做為參數(shù)給它,全局的each方法的具體實(shí)現(xiàn)如下:
// args 作為內(nèi)部成員的調(diào)用來(lái)使用
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // 當(dāng)object為jQuery對(duì)象時(shí),length非空
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
// 以下是客戶端程序進(jìn)行調(diào)用
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i表示索引值,value表示DOM元素
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[++i] ){}
}
return object;
}
現(xiàn)在我們關(guān)注下 for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 這句代碼;其中object[0]取得jQuery對(duì)象中的第一個(gè)DOM元素,通過(guò)for循環(huán),
得到遍歷整個(gè)jQuery對(duì)象中對(duì)應(yīng)的每個(gè)DOM元素,通過(guò)callback.call( value,i,value); 將callback的this對(duì)象指向value對(duì)象,并且傳遞兩個(gè)參數(shù),i表示索引值,value表示DOM元素;其中callback是類似于 function(index, elem) { } 的方法。所以就得到 $("").each(function(index, elem){ });
再來(lái)看看data([key],[value])的源代碼
Js代碼:
jQuery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;
// Gets all values
if ( key === undefined ) {
.....//處理沒(méi)有Key的情況,這里不是我們要討論的
return data;
}
// Sets multiple values
if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}
parts = key.split( ".", 2 );
parts[1] = parts[1] ? "." + parts[1] : "";
part = parts[1] + "!";
return jQuery.access( this, function( value ) {
if ( value === undefined ) {
。。。//這里是沒(méi)有value時(shí),是索取返回值的情況,這不是我們討論
}
parts[1] = value;
//如果我使用用$("div").data("a","aaa")),下面調(diào)用each前的this指的是$("div")這返回的對(duì)象,
this.each(function() {//注意了,這里是以每一個(gè)匹配的元素作為上下文來(lái)執(zhí)行一個(gè)函數(shù)
var self = jQuery( this );
self.triggerHandler( "setData" + part, parts );
//這里在元素上存放數(shù)據(jù),本質(zhì)還是委托data(element,[key],[value])來(lái)做的。
//看前面有分析過(guò)了。
//下面data( this, key, value )里的this指的是遍歷整個(gè)jQuery對(duì)象中對(duì)應(yīng)的每個(gè)DOM元素
//$("div")它對(duì)應(yīng)頁(yè)面中一個(gè)<div>數(shù)組。
jQuery.data( this, key, value )<span style="background-color: #ffcc00;">;//這名句會(huì)被循環(huán)多次執(zhí)行,也就是保存數(shù)據(jù)</span>。
//這里就是核心一句話。但要清楚看上面了它是在each(functipn(){})中的。
self.triggerHandler( "changeData" + part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
//在元素上移除存放的數(shù)據(jù)。具體實(shí)現(xiàn)如下:
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});
如果對(duì)于data([key],[value])的源代碼不是很了解,好吧,我就用一個(gè)例子來(lái)模仿實(shí)現(xiàn)它吧。
Js代碼:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var i=0;
$("#abc3").each(function() {
alert(++i);//只輸出1;因?yàn)橹挥幸粋€(gè)<div id="abc3">
});
alert("----");
var j=1;
$("div").each(function() {//以每一個(gè)匹配的元素作為上下文來(lái)執(zhí)行這個(gè)函數(shù)
$.data(this,"a","wwww");//這里的this就是指$("div"),
//分別遍歷每一個(gè)匹配的元素給它們每一個(gè)對(duì)象{}都保存一個(gè)key/value
alert(j++);//分別輸出1 ,2 ,3 因?yàn)橛腥齻€(gè)<div>元素
});
alert($("#test").data("a"));//返回wwww,
//是不是很驚呀,我沒(méi)有保存在它身上啊,怎么也有值,很明顯是它是查這個(gè)div節(jié)點(diǎn)上有沒(méi)有,
//肯定是有值了,因?yàn)樯厦娼o循環(huán)保存在div這Dom結(jié)點(diǎn)上了。
alert($("#test")===$("div"));//false證明兩新建的對(duì)象不是同一個(gè)。
alert($("div").data("a"));//返回wwww,
//這里也是一樣因?yàn)槭莇iv節(jié)點(diǎn)上都保存了"a"="wwww"這樣一個(gè)鍵值對(duì)了。
});
});
</script>
現(xiàn)在對(duì)data([key],[value])與jQuery.data(element,[key],[value])都有了解了吧,如果還是半懂,再回頭多看一遍,耐心地理解一下。其實(shí)表面上很不一樣。但本質(zhì)上還是有聯(lián)系的,現(xiàn)在明白原理后就可以請(qǐng)放心地使用了。jQuery.data(element,[key],[value])只把數(shù)據(jù)綁定到參數(shù)element節(jié)點(diǎn)上。data([key],[value])
如$("div").data("a","aaaa")它是把數(shù)據(jù)綁定每一個(gè)匹配div節(jié)點(diǎn)的元素上。
附加說(shuō)明下,文中所分析用到的是jquery-1.7.2.js的源代碼。下載地址:http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js
$("").data([key],[value])與jQuery.data(element,[key],[value])的區(qū)別
這兩個(gè)函數(shù)都是用來(lái)在元素上存放數(shù)據(jù)也就平時(shí)所說(shuō)的數(shù)據(jù)緩存,都返回jQuery對(duì)象,當(dāng)時(shí)我分別在使用它倆的時(shí)候真的嚇我一跳,區(qū)別可大了,真是不用不知道,一用嚇一跳??蠢酉劝桑笤俑鶕?jù)源代碼分析。
Js代碼:
復(fù)制代碼 代碼如下:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var e=$("div");//定義了兩jquery對(duì)象
var w=$("div");//e是不等于w的。
//首先使用data([key],[value])用法。
$(e).data("a","aaaa");//分別在e和w上保存Key一樣的數(shù)據(jù),
$(w).data("a","wwww");// 看它是否會(huì)覆蓋前面的,雖然是保存在不同對(duì)象上。
alert($(e).data("a"));//你猜到答案了嗎,里輸出是wwww;是不是有點(diǎn)意外?
alert(e===w)//false
alert($(w).data("a"));//這里也是wwww;
//使用jQuery.data(element,[key],[value])來(lái)存放數(shù)據(jù)。
$.data(e,"b","cccc");//分別在e和w上保存Key一樣的數(shù)據(jù),
$.data(w,"b","dddd");// 看它是否會(huì)覆蓋前面的,雖然是保存在不同對(duì)象上。
alert($.data(e,"b"));//應(yīng)該你能猜答案吧,輸出cccc
alert($.data(w,"b"));//這輸出dddd
});
});
</script>
看了上面的例子是不是發(fā)現(xiàn)data([key],[value])與jQuery.data(element,[key],[value])兩個(gè)根本就不一樣了對(duì)吧?它們之間到底有沒(méi)有關(guān)系呢。怎么data([key],[value])會(huì)覆蓋前面key相同的值呢?
而jQuery.data(element,[key],[value])只要是綁定到不同的對(duì)象上都不會(huì)造成覆蓋。是這樣嗎?那來(lái)研究下它們的源代碼吧。
先看jQuery.data(element,[key],[value])源代碼。
Js代碼:
復(fù)制代碼 代碼如下:
jQuery.extend({
cache: {},
// Please use with caution
uuid: 0,
// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
....
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
// 是否可以附加數(shù)據(jù),不可以則直接返回
if ( !jQuery.acceptData( elem ) ) {
return;
}
var privateCache, thisCache, ret,
//jQuery.expando這是一個(gè)唯一的字符串,是這介jquery對(duì)象產(chǎn)生的時(shí)候就生成了。
internalKey = jQuery.expando,
getByName = typeof name === "string",
// 必須區(qū)分處理DOM元素和JS對(duì)象,因?yàn)镮E6-7不能垃圾回收對(duì)象跨DOM對(duì)象和JS對(duì)象進(jìn)行的引用屬性
isNode = elem.nodeType,
// 如果是DOM元素,則使用全局的jQuery.cache
// 如果是JS對(duì)象,則直接附加到對(duì)象上
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
isEvents = name === "events";
// 避免做更多的不必要工作,當(dāng)嘗試在一個(gè)沒(méi)有任何數(shù)據(jù)的對(duì)象上獲取數(shù)據(jù)時(shí)
// 對(duì)象沒(méi)有任何數(shù)據(jù),直接返回
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// id不存在的話就生成一個(gè)
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
// 如果是DOM元素則在元素上產(chǎn)生唯一的ID 并且以jQuery.expando
//為屬性值為id保存在elem元素上,以便以后再根據(jù)jQuery.expando來(lái)查找ID。
elem[ internalKey ] = id = ++jQuery.uuid;
} else {
// JS對(duì)象則直接使用jQuery.expando,既然是直接附加到對(duì)象上,又何必要id呢?
// 避免與其他屬性沖突!
id = internalKey;
}
}
//// 當(dāng)我們?cè)囍L問(wèn)一個(gè)鍵是否含有值的時(shí)候,如果不存在jQuery.cache[id]值,
// 初始化jQuery.cache[id]值 為一個(gè)空對(duì)象{}
if ( !cache[ id ] ) {
cache[ id ] = {};
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
// data是接收對(duì)象和函數(shù),淺拷貝
if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) {
cache[ id ] = jQuery.extend( cache[ id ], name );
} else {
cache[ id ].data = jQuery.extend( cache[ id ].data, name );
}
}
/ 存儲(chǔ)對(duì)象,存放了所有數(shù)據(jù)的映射對(duì)象
privateCache = thisCache = cache[ id ];
// jQuery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data.
// jQuery內(nèi)部數(shù)據(jù)存在一個(gè)獨(dú)立的對(duì)象(thisCache.data==thisCache[ internalKey ])
//上,為了避免內(nèi)部數(shù)據(jù)和用戶定義數(shù)據(jù)沖突
if ( !pvt ) {
// 存放私有數(shù)據(jù)的對(duì)象不存在,則創(chuàng)建一個(gè){}
if ( !thisCache.data ) {
thisCache.data = {};
}
// 使用私有數(shù)據(jù)對(duì)象替換thisCache
thisCache = thisCache.data;
}
// 如果data不是undefined,表示傳入了data參數(shù),則存儲(chǔ)data到name屬性上
if ( data !== undefined ) {
// jQuery.camelCase( name )作用是如果傳入的是object/function,不做轉(zhuǎn)換,
//只有傳入的name是字符串才會(huì)轉(zhuǎn)換。所以最終保存下來(lái)的是key/value對(duì);
thisCache[ jQuery.camelCase( name ) ] = data;
}
//從這以后下面的代碼都是處理data: function( elem, name)data為空,求返回值data的情況了。
if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}
// 如果name是字符串,則返回data
// 如果不是,則返回整個(gè)存儲(chǔ)對(duì)象
if ( getByName ) {
// First Try to find as-is property data
ret = thisCache[ name ];
// Test for null|undefined property data
if ( ret == null ) {
// Try to find the camelCased property
ret = thisCache[ jQuery.camelCase( name ) ];
}
} else {
ret = thisCache;
}
return ret;
},
............
});
請(qǐng)看圖

看jQuery.data(element,[key],[value])源代碼后可以知道,每一個(gè)element都會(huì)有自己的一個(gè){key:value}對(duì)象保存著數(shù)據(jù),所以新建的對(duì)象就算有key相同它也不會(huì)覆蓋原來(lái)存在的對(duì)象key所對(duì)應(yīng)的value,因?yàn)樾聦?duì)象保存是是在另一個(gè){key:value}對(duì)象中。
接下來(lái)要分析data([key],[value])源代碼使用到了each(callback),在分析它之前先看下each(callback)用法和源代碼。
Js代碼:
復(fù)制代碼 代碼如下:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var i=0;
$("#abc3").each(function() {
alert(++i);//只輸出1;因?yàn)橹挥幸粋€(gè)<div id="abc3">
});
alert("----");
var j=0;
$("div").each(function() {
alert(++j);//分別輸出1,2,3;因?yàn)橛腥齻€(gè)<div>所以循環(huán)三遍
});
});
});
</script>
現(xiàn)在來(lái)看each方法的具體實(shí)現(xiàn)如下:
jQuery.fn = jQuery.prototype = {
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
}
可以看到它返回的是全局的each方法,并且將自身jQuery對(duì)象做為參數(shù)給它,全局的each方法的具體實(shí)現(xiàn)如下:
// args 作為內(nèi)部成員的調(diào)用來(lái)使用
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // 當(dāng)object為jQuery對(duì)象時(shí),length非空
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
// 以下是客戶端程序進(jìn)行調(diào)用
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i表示索引值,value表示DOM元素
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[++i] ){}
}
return object;
}
現(xiàn)在我們關(guān)注下 for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 這句代碼;其中object[0]取得jQuery對(duì)象中的第一個(gè)DOM元素,通過(guò)for循環(huán),
得到遍歷整個(gè)jQuery對(duì)象中對(duì)應(yīng)的每個(gè)DOM元素,通過(guò)callback.call( value,i,value); 將callback的this對(duì)象指向value對(duì)象,并且傳遞兩個(gè)參數(shù),i表示索引值,value表示DOM元素;其中callback是類似于 function(index, elem) { } 的方法。所以就得到 $("").each(function(index, elem){ });
再來(lái)看看data([key],[value])的源代碼
Js代碼:
復(fù)制代碼 代碼如下:
jQuery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;
// Gets all values
if ( key === undefined ) {
.....//處理沒(méi)有Key的情況,這里不是我們要討論的
return data;
}
// Sets multiple values
if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}
parts = key.split( ".", 2 );
parts[1] = parts[1] ? "." + parts[1] : "";
part = parts[1] + "!";
return jQuery.access( this, function( value ) {
if ( value === undefined ) {
。。。//這里是沒(méi)有value時(shí),是索取返回值的情況,這不是我們討論
}
parts[1] = value;
//如果我使用用$("div").data("a","aaa")),下面調(diào)用each前的this指的是$("div")這返回的對(duì)象,
this.each(function() {//注意了,這里是以每一個(gè)匹配的元素作為上下文來(lái)執(zhí)行一個(gè)函數(shù)
var self = jQuery( this );
self.triggerHandler( "setData" + part, parts );
//這里在元素上存放數(shù)據(jù),本質(zhì)還是委托data(element,[key],[value])來(lái)做的。
//看前面有分析過(guò)了。
//下面data( this, key, value )里的this指的是遍歷整個(gè)jQuery對(duì)象中對(duì)應(yīng)的每個(gè)DOM元素
//$("div")它對(duì)應(yīng)頁(yè)面中一個(gè)<div>數(shù)組。
jQuery.data( this, key, value )<span style="background-color: #ffcc00;">;//這名句會(huì)被循環(huán)多次執(zhí)行,也就是保存數(shù)據(jù)</span>。
//這里就是核心一句話。但要清楚看上面了它是在each(functipn(){})中的。
self.triggerHandler( "changeData" + part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
//在元素上移除存放的數(shù)據(jù)。具體實(shí)現(xiàn)如下:
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});
如果對(duì)于data([key],[value])的源代碼不是很了解,好吧,我就用一個(gè)例子來(lái)模仿實(shí)現(xiàn)它吧。
Js代碼:
復(fù)制代碼 代碼如下:
<div id="test2" onclick="test()">test2</div>
<div id="abc3" onclick="test()">test3</div>
<div id="test" onclick="test()">test</div>
<p id="ttt">aaaa</p>
<script>
$(document).ready(function(){
$("#test").click(function(){
alert("JQUERY");
var i=0;
$("#abc3").each(function() {
alert(++i);//只輸出1;因?yàn)橹挥幸粋€(gè)<div id="abc3">
});
alert("----");
var j=1;
$("div").each(function() {//以每一個(gè)匹配的元素作為上下文來(lái)執(zhí)行這個(gè)函數(shù)
$.data(this,"a","wwww");//這里的this就是指$("div"),
//分別遍歷每一個(gè)匹配的元素給它們每一個(gè)對(duì)象{}都保存一個(gè)key/value
alert(j++);//分別輸出1 ,2 ,3 因?yàn)橛腥齻€(gè)<div>元素
});
alert($("#test").data("a"));//返回wwww,
//是不是很驚呀,我沒(méi)有保存在它身上啊,怎么也有值,很明顯是它是查這個(gè)div節(jié)點(diǎn)上有沒(méi)有,
//肯定是有值了,因?yàn)樯厦娼o循環(huán)保存在div這Dom結(jié)點(diǎn)上了。
alert($("#test")===$("div"));//false證明兩新建的對(duì)象不是同一個(gè)。
alert($("div").data("a"));//返回wwww,
//這里也是一樣因?yàn)槭莇iv節(jié)點(diǎn)上都保存了"a"="wwww"這樣一個(gè)鍵值對(duì)了。
});
});
</script>
現(xiàn)在對(duì)data([key],[value])與jQuery.data(element,[key],[value])都有了解了吧,如果還是半懂,再回頭多看一遍,耐心地理解一下。其實(shí)表面上很不一樣。但本質(zhì)上還是有聯(lián)系的,現(xiàn)在明白原理后就可以請(qǐng)放心地使用了。jQuery.data(element,[key],[value])只把數(shù)據(jù)綁定到參數(shù)element節(jié)點(diǎn)上。data([key],[value])
如$("div").data("a","aaaa")它是把數(shù)據(jù)綁定每一個(gè)匹配div節(jié)點(diǎn)的元素上。
附加說(shuō)明下,文中所分析用到的是jquery-1.7.2.js的源代碼。下載地址:http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js
您可能感興趣的文章:
- 禁止JQuery中的load方法裝載IE緩存中文件的方法
- jQuery 數(shù)據(jù)緩存data(name, value)詳解及實(shí)現(xiàn)
- jQuery ajax cache緩存問(wèn)題
- 讀jQuery之六 緩存數(shù)據(jù)功能介紹
- ie下jquery.getJSON的緩存問(wèn)題的處理方法
- 關(guān)于jQuery對(duì)象數(shù)據(jù)緩存Cache原理以及jQuery.data詳解
- jquery 緩存問(wèn)題的幾個(gè)解決方法
- 快速解決jquery之get緩存問(wèn)題的最簡(jiǎn)單方法介紹
- jQuery中ajax的使用與緩存問(wèn)題的解決方法
- ASP.NET MVC中使用jQuery時(shí)的瀏覽器緩存問(wèn)題詳解
相關(guān)文章
js判斷復(fù)選框是否選中的方法示例【基于jQuery】
這篇文章主要介紹了js判斷復(fù)選框是否選中的方法,結(jié)合實(shí)例形式分析了基于jQuery實(shí)現(xiàn)的復(fù)選框選中判斷相關(guān)操作技巧,需要的朋友可以參考下2019-10-10基于Jquery的標(biāo)簽智能驗(yàn)證實(shí)現(xiàn)代碼
一直在尋找最快捷方便的信息驗(yàn)證方法,之前自己編過(guò)JS版驗(yàn)證但要寫很多輔助代碼,經(jīng)過(guò)許多次改進(jìn),還是覺(jué)得太麻煩代碼還多,維護(hù)起太費(fèi)盡。2010-12-12jQuery滾動(dòng)加載圖片實(shí)現(xiàn)原理
這篇文章主要介紹了jQuery滾動(dòng)加載圖片實(shí)現(xiàn)原理,通過(guò)四個(gè)方面來(lái)說(shuō)明懶加載技術(shù)的原理,感興趣的小伙伴們可以參考一下2015-12-12Jquery根據(jù)瀏覽器窗口改變調(diào)整大小的方法
下面小編就為大家?guī)?lái)一篇Jquery根據(jù)瀏覽器窗口改變調(diào)整大小的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02jQuery實(shí)現(xiàn)懸浮在右上角的網(wǎng)頁(yè)客服效果代碼
這篇文章主要介紹了jQuery實(shí)現(xiàn)懸浮在右上角的網(wǎng)頁(yè)客服效果代碼,涉及jQuery響應(yīng)鼠標(biāo)事件動(dòng)態(tài)變換頁(yè)面元素樣式的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10jQuery.cookie.js實(shí)現(xiàn)記錄最近瀏覽過(guò)的商品功能示例
這篇文章主要介紹了jQuery.cookie.js實(shí)現(xiàn)記錄最近瀏覽過(guò)的商品功能,結(jié)合實(shí)例形式分析了基于jQuery.cookie.js插件創(chuàng)建cookie及保存瀏覽記錄的操作技巧,需要的朋友可以參考下2017-01-01