There are many online tutorials on how to use jQuery.data(..) to implement data caching, but there are two commonly used by users: data([key],[value]) and jQuery.data(element,[key] , [value]) There are almost no articles that clearly explain the difference between the two, so I used it, studied it and shared it with everyone.
The difference between $("").data([key],[value]) and jQuery.data(element,[key],[value])
Both functions are used on elements Storing data is also commonly referred to as data caching, and both return jQuery objects. I was really shocked when I used them respectively. The difference is huge. I really don’t need to know, but I was shocked when I used them. Let’s look at the example first, and then analyze it based on the source code.
test2
test3
test
aaaa
<script> <br>$(document).ready(function(){ <br>$("#test").click(function(){ <br>alert("JQUERY"); <br><br>var e=$("div");//Two jquery objects are defined<br>var w=$("div");//e is not equal to w. <br><br>//First use data([key],[value]) usage. .data("a","aaaa");//Save the same data with Key on e and w respectively, <br>$(w).data("a","wwww");// See if it It will overwrite the previous one, although it is saved in a different object. <br>alert($(e).data("a"));//Did you guess the answer? Is it a bit surprising that the output is wwww? <br>alert(e===w)//false <br>alert($(w).data("a"));//This is also wwww; <br><br>//Use jQuery.data (element,[key],[value]) to store data. <br>$.data(e,"b","cccc");//Save the same data on e and w respectively, <br> $.data(w,"b","dddd");//See if it will overwrite the previous one, although it is saved on a different object. <br>alert($.data(e,"b")); //You should be able to guess the answer, output cccc <br>alert($.data(w,"b"));//This output dddd <br><br>}); <br>}); <br></script>
After reading the above example, did you find that data([key],[value]) and jQuery.data(element,[key],[value]) are fundamentally different, right? Is there any relationship between them? Why does data([key],[value]) overwrite the same value of the previous key?
And jQuery.data(element,[key],[value]) will not cause overwriting as long as it is bound to different objects. is that so? Let’s study their source code.
Look at the jQuery.data(element,[key],[value]) source code first.
Copy code The code is as follows:
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 */ ) {
// Whether data can be appended, if not, return directly
if ( !jQuery.acceptData( elem ) ) {
return;
}
var privateCache, thisCache, ret,
//jQuery.expando This is a unique string that is This jquery object is generated when it is generated.
internalKey = jQuery.expando,
getByName = typeof name === "string",
// DOM elements and JS objects must be processed separately. , because IE6-7 cannot garbage collect object reference attributes across DOM objects and JS objects
isNode = elem.nodeType,
// If it is a DOM element, use the global jQuery.cache
// If it is a JS object, attach it directly to the object
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";
// Avoid doing more unnecessary work when trying to get data on an object without any data
// If the object does not have any data, return directly
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// id If it does not exist, generate a
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
// If it is a DOM element, generate a unique ID on the element and use jQuery.expando
// as the attribute value and save the id on the elem element so that it can be searched later based on jQuery.expando ID.
elem[ internalKey ] = id = jQuery.uuid;
} else {
//JS objects use jQuery.expando directly. Since it is directly attached to the object, why do we need the id?
// Avoid conflicts with other attributes!
id = internalKey;
}
}
//// When we try to access whether a key contains a value, if the jQuery.cache[id] value does not exist,
//Initialize jQuery.cache[id] value to an empty object {}
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 is to receive objects and functions, shallow copy
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 );
}
}
/ Storage object, a mapping object that stores all data
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 Internal data exists in an independent object (thisCache.data==thisCache[internalKey])
//On, in order to avoid conflicts between internal data and user-defined data
if ( !pvt ) {
// Store private If the data object does not exist, create one {}
if ( !thisCache.data ) {
thisCache.data = {};
}
// Replace thisCache with a private data object
thisCache = thisCache.data;
}
// If data is not undefined, it means that the data parameter is passed in, then the data is stored in the name attribute
if ( data !== undefined ) {
/ / The function of jQuery.camelCase(name) is that if the object/function is passed in, no conversion will be performed.
//Only the name passed in is a string. So what is finally saved is the key/value pair;
thisCache[ jQuery.camelCase( name ) ] = data;
}
//From now on, the following code processes data: function (elem, name) data is empty, find the return value data.
if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}
// If name is a string, return data
/ / If not, return the entire storage object
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;
},
............
});
Please see the picture.
Looking at the jQuery.data(element,[key],[value]) source code, you can know that each element will have its own {key:value} object to store the data, so the newly created object will have the same key It will not overwrite the value corresponding to the original existing object key, because the new object is saved in another {key:value} object.
Next, we need to analyze the source code of data([key],[value]), which uses each(callback). Before analyzing it, let’s take a look at the usage and source code of each(callback).
Js code:
test2
test3
test
aaaa
<script> <br>$(document).ready(function(){ <br>$("#test").click(function(){ <br>alert("JQUERY"); <br><br>var i=0; <br>$("#abc3").each( function() { <br>alert( i);//Only output 1; because there is only one <div id="abc3"> <br>}); <br>alert("----"); <br>var j=0; <br>$("div").each(function() { <br>alert( j);//Output 1, 2, 3 respectively; because there are three <div> Loop three times <br>}); <br>}); <br>}); <br></script>
Now let’s look at the specific implementation of each method as follows:
jQuery. fn = jQuery.prototype = {
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
}
You can see What it returns is the global each method, and its own jQuery object is given to it as a parameter. The specific implementation of the global each method is as follows:
// args is used as a call to internal members
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // When object is a jQuery object, length is not empty
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;
// The following is the client program to call
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i represents the index value, value represents the DOM element
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[ i] ){}
}
return object;
}
Now we focus on the code for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[ i] ){}; Among them, object[0] gets the first DOM element in the jQuery object. Through the for loop,
gets to traverse each corresponding DOM element in the entire jQuery object. Through callback.call(value,i,value);, callback The this object points to the value object, and two parameters are passed, i represents the index value, and value represents the DOM element; callback is a method similar to function(index, elem) { }. So we get $("").each(function(index, elem){ });
Let’s take a look at the source code of data([key],[value])
Js code:
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 ) {
.....//Handle without Key situation, this is not what we are going to discuss
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 ) {
. //This is the case where the return value is obtained when there is no value. This is not what we are discussing
} <.>
parts[1] = value;
//If I use $("div").data("a","aaa")), below call the this pointer before each is the object returned by $("div"),
this.each(function() {//Note, here we use each matching element as the context to execute a function
var self = jQuery ( this );
self.triggerHandler( "setData" part, parts );
//The data is stored on the element here. The essence is to delegate data(element,[key],[value ]).
//See the previous analysis.
//This in data(this, key, value) below refers to traversing each corresponding DOM element in the entire jQuery object
//$("div") It corresponds to a
array in the page.
jQuery.data( this, key, value );//This statement will be executed in a loop multiple times, that is, the data is saved .
//Here is the core sentence. But please see clearly above that it is in each(functipn(){}).
self.triggerHandler( "changeData" part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
//Remove stored data on the element. The specific implementation is as follows:
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});
If you don’t know much about the source code of data([key],[value]), well, I will use an example to imitate it.
Js code:
test2
test3
test
aaaa
<script> <br>$(document).ready(function(){ <br>$("#test").click(function(){ <br>alert("JQUERY"); <br><br>var i=0; <br>$("#abc3").each( function() { <br>alert( i);//Only output 1; because there is only one <div id="abc3"> <br>}); <br>alert("----"); <br>var j=1; <br>$("div").each(function() {//Execute this function with each matching element as the context<br><br>$.data(this, "a","wwww");//This here refers to $("div"), <br>//Traverse each matching element separately and save a key/value for each of their objects {} <br>alert(j );//Output 1, 2, 3 respectively because there are three <div> elements <br>}); <br>alert($("#test").data("a")); //Return to wwww, <br>//Aren't you surprised? I didn't save it in it. Why is there a value? It's obvious that it is checking whether there is one on this div node. <br>//There must be a value. Yes, because the above loop is saved in the Dom node of div <br>alert($("#test")===$("div"));//false proves that the two newly created objects are not the same. . <br><br>alert($("div").data("a"));//Return wwww, <br>//The same is true here because "a"=" is saved on the div node. wwww" such a key value is correct. <br>}); <br>}); <br></script>
Now you understand data([key],[value]) and jQuery.data(element,[key],[value]). If you still don’t understand it, go back and read it again and patiently understand it. one time. In fact, it looks very different on the surface. But there is still a connection in essence. Now that you understand the principle, you can use it with confidence. jQuery.data(element,[key],[value]) only binds data to the parameter element node. data([key],[value])
For example, $("div").data("a","aaaa"), it binds data to each element that matches the div node.
As an additional note, the source code of
jquery-1.7.2.js is used in the analysis in this article. Download address: http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js