The data caching system should first be introduced by jQuery1.2, when its event system completes copying de great God's addevent.js, and Addevent has a flaw in implementation, it puts the callback of the event on Eventtarget, which triggers a circular reference, if Eventtarget is wind Ow object, and will cause global pollution. With the data caching system, in addition to avoiding these two risks, we can effectively save the intermediate variables produced by different methods, and these variables will be useful to the other module's method, decoupling the dependencies between the methods. For jquery, its event cloning and even subsequent queue implementations are inseparable from the caching system.
jQuery1.2 has added two static methods to the core module, data and Removedata. Data needless to say, as with other jquery methods, read-write binding. jquery's caching system is to put all the data on top of the $.cache, and then for each element node to use the caching system, the Document object and the Window object are assigned a UUID. The UUID's property name is a random custom attribute, "JQuery" + (new Date ()). GetTime (), the value is an integer and is incremented from zero. But the UUID is always attached to an object, if that object is window, it is not a global pollution, so the jquery inside determines that it is a Window object, mapped to an empty object called Windowdata, and then the UUID added above it. With the UUID, when we first access the caching system, we open an empty object (the cache body) in the $.cache object to place the object associated with the target. This is a bit like a bank account, the value of the UUID is the passbook. Removedata will delete no longer need to save the data, if to the end, the data is erased, it does not have any key-value pairs, become empty objects, jquery will delete this object from the $.cache, and remove the UUID from the target object.
Copy Code code as follows:
jQuery1.2.3
var expando = "JQuery" + (new Date ()). GetTime (), uuid = 0, windowdata = {};
Jquery.extend ({
Cache: {},
Data:function (elem, name, data) {
Elem = Elem = = window? windowdata:elem;//Special handling of Window objects
var id = elem[expando];
if (!id)//If there is no UUID, the new one is set
id = elem[expando] = ++uuid;
If you do not open an account in $.cache, open the account first
if (name &&!jquery.cache[ID])
jquery.cache[id] = {};
When the third argument is not undefined, the write operation
if (data!= undefined)
jquery.cache[ID [Name] = data;
If there is only one argument, the cached object is returned and two parameters return the target data
return name? jquery.cache[ID [name]: ID;
},
Removedata:function (Elem, name) {
Elem = Elem = = window? Windowdata:elem;
var id = elem[expando];
if (name) {//removing Target data
if (jquery.cache[id]) {
Delete jquery.cache[ID [name];
name = "";
for (name in jquery.cache[ID])
Break
Traversing the cache body, if not NULL, the name is overwritten, and if it is not overwritten,!name is true.
This raises the call to this method again, but this time it is a single parameter that removes the cache body.
if (!name)
Jquery.removedata (Elem);
}
} else {
Remove the UUID, but the use of Delete to the element under IE is thrown incorrectly
try {
Delete elem[expando];
catch (e) {
if (Elem.removeattribute)
Elem.removeattribute (expando);
}//Cancellation Account
Delete jquery.cache[ID];
}
}
})
jquery added two prototype methods, data and Removedata, with the same name in 1.2.3 to facilitate chained operations and assembly operations. and add GetData to the data, SetData the trigger logic of the custom event.
In 1.3, the data caching system is finally independent of a module data.js (the internal development of the Division), and added two sets of methods, namespaces on the queue and dequeue, the prototype queue and dequeue. The purpose of the queue is clearly to cache a set of data for the Animation module service. Dequeue is to delete one from a set of data.
Copy Code code as follows:
jQuery1.3
Jquery.extend ({
Queue:function (Elem, type, data) {
if (elem) {
Type = (Type | | "FX") + "queue";
var q = jquery.data (Elem, type);
if (!q | | jquery.isarray (DATA))//ensures that an array is stored
Q = Jquery.data (Elem, type, Jquery.makearray (data));
else if (data)//Then add something to this data
Q.push (data);
}
return q;
},
Dequeue:function (Elem, type) {
var queue = Jquery.queue (Elem, type),
fn = Queue.shift ();//Then delete one, early it is a callback to place the animation, delete it and call it,
But did not do it as a function of the decision, is not expected to write to the document, for internal use
if (!type | | type = = "FX")
fn = queue[0];
if (fn!== undefined)
Fn.call (Elem);
}
})
Example of a call to the FX module animate method:
Copy Code code as follows:
Each is to handle multiple animations in parallel, and queue is one after another to handle multiple animations
this[Optall.queue = = False? ' Each ': ' Queue ' (function () {/* * * * * * *)
Adding a custom attribute on the element also raises a problem. If we copy this element, the attribute will also be duplicated, causing the two elements to have the same UUID value and the data being incorrectly manipulated. jquery's early replication node implementation is very simple, if the element's CloneNode method does not replicate the event to use CloneNode, otherwise use the element's outerhtml, or the parent node's innerHTML, use the Clean method to parse a new element out. But outerHTML and innerHTML both have explicit attributes written in it, so they need to be cleaned out with a positive.
Copy Code code as follows:
jQuery1.3.2 Core.js Clone method
var ret = This.map (function () {
if (!jquery.support.nocloneevent &&!jquery.isxmldoc (this)) {
var html = this.outerhtml;
if (!html) {
var div = this.ownerDocument.createElement ("div");
Div.appendchild (This.clonenode (true));
html = div.innerhtml;
}
Return Jquery.clean ([Html.replace (/jquery\d+=) (?: \ D+|null) "/g," "). Replace (/^\s*/," ")]) [0];
} else
Return This.clonenode (TRUE);
});
jQuery1.4 found IE if for object, Ember, applet these three old to access external resources of the label may be thrown wrong. Since the element node of the old IE is just a COM wrapper, once the resource is introduced, it becomes an instance of that resource, and they have strict access control and cannot add members as normal JS objects. So jquery will change a knife, but the three kinds of labels, it does not cache data for it. jquery has a hash called NoData, which detects the label of an element node.
Copy Code code as follows:
NoData: {"Embed": true,
' Object ': true,
' Applet ': true},
Code Defense
if (Elem.nodename && jquery.nodata[elem.nodename.tolowercase ()]) {
Return
}
The jQuery1.4 also improves the $.data, allowing the second parameter to be an object to facilitate the storage of multiple data. The custom attribute expando for the UUID is also placed under the namespace. The queue and Dequeue methods are stripped down into a new module.
The jQuery1.43 brings three improvements.
The first is to add a Changedata customization method. But this method does not have any sales, but the product manager's narcissism.
The logic that detects whether an element node supports adding custom attributes is independent of a method called Acceptdata. Because the jquery team found the flash resource loaded with the OBJECT tag, it could add custom attributes, and decided to spared the situation. ie when loading flash, the object needs to specify a property called ClassID, the value is clsid:d27cdb6e-ae6d-11cf-96b8-444553540000, so the detection logic becomes very complex, because of data, Removedata to use, independent of the effective save bit.
HTML5 a response to the behavior of people casually adding custom attributes, adding a caching mechanism called "data-*". When user-set properties begin with "data-", they are saved to the DataSet object of the element node. This makes it possible for people to use HTML5 to cache data, or to use jquery's caching system to save data, which is a bit of a dud. So jquery's data on the prototype is enhanced, and when the user accesses the element node for the first time, it iterates through all of its "data-" Custom attributes (in order to take care of the old ie, can't traverse the dataset directly) and put them in the jquery cache. Then when the user takes the data, the "data-" custom attribute is accessed from the cache system without using setattribute. But the HTML5 cache system is very weak and can only save strings (this is certainly for circular references), so jquery restores them to various data types, such as "null", "false", "true" to null, FALSE, True, A string that matches the number format is converted to a number, and an attempt is made to turn into an object if it ends with "{".
Copy Code code as follows:
jQuery1.43 $.fn.data
Rbrace =/^ (?: \ {.*\}|\[.*\])$/;
if (data = = undefined && this.length) {
data = Jquery.data (This[0], key);
if (data = = undefined && This[0].nodetype = 1) {
data = This[0].getattribute ("data-" + key);
if (typeof data = = "string") {
try {
data = data = = "true"? true:
data = = "false"? False:
data = = "Null"? Null:
!jquery.isnan (data)? parsefloat (data):
Rbrace.test (data)? Jquery.parsejson (data):
Data
catch (e) {}
} else {
data = undefined;
}
}
}
The jQuery1.5 also brought three improvements. At that time JQuery had defeated Prototype.js in 1.42, the heyday, Matthew Effect, and user volume was exploding. It focuses instead on improving performance and entering the fix bug phase (the more users, the more free testers, the larger the test coverage).
Improved expando, originally based on time truncation, is now a version number plus a random number. So the user may introduce multiple versions of jquery on one page.
Whether or not the logic of this data is drawn into a hasdata method, the "data-*" property that handles the HTML5 is also drawn into a private method dataattr. They are all for the sake of logic to become clearer. Dataattr uses Json.parse, because this JSON might be introduced by Json2.js, and Json2.js has a very bad place to add a Tojson method for a series of native types, causing the for in loop to determine if an error is an empty object. jquery was forced to do a isemptydataobject method of processing.
jquery's data caching system was originally differentiated for event System services, and later it was the infrastructure of many internal modules. In other words, it stores many of the framework user variables (System data), but once it is exposed to the document, users will also use data to save the information used in their business (user data). Previously, user small, variable name conflict is less likely, plus jquery for these system data to select some unusual names, __class__, __change__ or add a suffix what, did not receive any complaints. When jquery becomes a world-class framework, the user data name kills the system data name, causing the event system or other modules to be paralyzed. jquery began to transform the cache, it was an object, what data are thrown inside. Now it opens up a child object in this cache, with the key named Random Jquery.expando value, and if the system data is stored inside. But the events system data is placed directly above the cache for the sake of forward compatibility. As for, how to distinguish is the system data, very simple, directly add the fourth parameter in the data method, the truth value is the system data. The Removedata also provides a third parameter for deleting system data. A new _data method is also set up to be used specifically for operating system data. The following is the structure diagram of the cache body:
Copy Code code as follows:
var cache = {
jquery14312343254:{/* Placement System Data * *}
Events: {/"place event name with its corresponding callback list"/}
/* Place user data here/*
}
jQuery1.7 to the cache body has been improved, the system variable placed in the data object, for this decision cache body is empty also need to make corresponding improvement, now to skip Tojson and data. The new structure is as follows:
Copy Code code as follows:
var cache = {
data:{/* to place user data */}
/* Place system data here/*
}
jQuery1.8 has added an array called Deleteids, which is used to reuse uuid, but is short-lived. The value of the UUID is not jquery.uuid from 1.8, instead of the jquery.guid increment generation. Significant improvements after jQuery1.83, the implementation of operational data is drawn out as a private method, and the method of namespaces and prototypes is only a proxy, and is divided into two sets of methods, which manipulate the data, Removedata, and _data,_removedata of the data of the user. Now the caching system is a huge family.
In the final analysis, data caching is a one-to-one relationship between the target object and the cached body, and then the data is manipulated on the cached body, and the complexity is set in the former. And in a common JS object to check a property is never difficult, users can not play tricks. From the principle of software design, this is also the best result (consistent with KISS principles and responsibilities of a single).