A simple study of jquery caching technology

Source: Internet
Author: User
Tags extend garbage collection instance method json numeric value tojson unique id uuid

If compared to the Java language World, the jquery data module and the jquery queue module are similar to the Java Collection framework. The JQuery data module functions simply as a "crud operation" to "delete and modify the cache" on an element. "An element" may be a native DOM object, or it may be a JS kernel object, and the JQuery data module treats them differently. According to the jquery Universal programming style, the general writing and reading of the data is designed to the same method, and the update belongs to the write operation type, so there are only two methods of--data () and Removedata (), of course, usually design a hasdata () method to determine whether the data exists. In addition, the jquery data module takes into account the requirements of the private data store and implements a scheme _data () from logic (not syntax), and for some special DOM elements that do not support data storage, jquery data gives a method of judging acceptdata ().

An API for a JQuery data module

First look at several common usage methods of the jquery data module.

1 Writing data
(1) write a single piece of data
Jquery.prototype instance method: $ ("x"). Data ("P1", "V1");
JQuery static method: Jquery.data (Elem, "P1", "V1");
(2) write more than one data
Jquery.prototype instance method: $ ("x"). Data ({"P1": "V1", "P2": "V2", "P3": "V3"});
JQuery static method: Jquery.data (Elem, {"P1": "V1", "P2": "V2", "P3": "V3"});

2 reading data
(1) Read single data
Jquery.prototype instance method: $ ("x"). Data ("P1");
JQuery static method: Jquery.data (Elem, "P1");
(2) Read all data
Jquery.prototype instance method: $ ("x"). data ();
JQuery static method: Jquery.data (Elem);

3 Delete Data
Jquery.prototype instance method: $ ("x"). Removedata ("P1");
JQuery static method: Jquery.removedata (Elem, "P1");

Two design scheme

The

JQuery Data Module design idea is relatively simple compared to other modules, here is a summary.
1 for Native DOM objects
First exclude DOM element types that cannot accept the data cache, which are marked in the NoData object. Dom types that cannot accept the data cache as long as the DOM object node name and the corresponding attribute conform to the noData set rule are: ' var match = jquery.nodata[elem.nodeName.toLowerCase ()]; ', The corresponding Acceptdata () method returns FALSE.
for DOM objects that accept data caching, the data for each object is cached in the global cache object Jquery.cache, not in the DOM object itself! This is the key point, in the global cache object Jquery.cache for each DOM object to open a cache object cache the DOM's data, which leads to the question is: How to correlate different DOM objects to the global cache object Jquery.cache different cache objects? JQuery's solution is to add a property to each Dom object named ' Jquery.expando ', which consists of three parts: ' JQuery ', ' Version ', ' Random numeric value ', whose rule is ' expando: ' JQuery "+ (JQuery.fn.jquery + math.random ()). Replace (/\d/g," "), ' the value of this variable is designed to maximize the guarantee that the user's custom variable values are not identical to the conflict. This property name is consistent for all DOM objects that can cache data, but the value of this property for each DOM object is unique, similar to the primary key rule of a relational database table, uniquely generated by a global UUID ' elem[jquery.expando] = ID = + + Jquery.uuid ', this value is a unique and incremented integer value. The value ' Jquery.uuid ' of the
Dom object property ' Jquery.expando ' will be the key of the global cache object, and the value of the global cache object is a separate cache object Thiscache that stores all data that corresponds to the DOM object that needs to be cached. This allows the unique cache object to be in the global cache object Jquery.cache, based on the property values of each different DOM object, and the crud operations of the DOM object cache data are plainly the crud operations of the Thiscache for this isolated cache object.

2 for JS kernel objects
JS Kernel object cache is not so around, because the JS kernel object itself can open up a property as a stand-alone cache object Thiscache, the name of this property is also simple, is ' jquery.expando ' value, all JS kernel object cache attribute name are consistent. As for why the DOM object cannot store cached data as directly as the JS kernel object, the reason given in the source code is that it involves the memory recycle mechanism of the browser-if you add a standalone cache object directly to the DOM object, the DOM object, because it references a standalone cached object, The garbage collection mechanism will not be able to determine that the DOM object can be recycled according to the ' reference notation ', so that long running accumulation may result in oom (this understanding may not be accurate).

Source analysis of the three main methods

1 Jquery.data (Elem, name, data, PVT/* Internal use only * *) method source code
Because the data one method undertakes the c/r/u three kinds of operation, so its parameter invocation and the internal realization logic are more diverse.

Data:function (elem, name, data, PVT/* Internal use only * *) {
/** is returned directly for DOM type objects that cannot be read or written. */
if (!jquery.acceptdata (Elem)) {
Return
}
/**
Determine if the method is read or write--name parameters and the data parameter are all undefined words are read all, the name parameter is string type and the data is undefined is read single, other calls are write.
Determine whether the method is a DOM object operation or a JS object operation-directly to see if the Elem parameter has nodetype properties.
Determining that the id--of the current Elem object is a DOM object is elem[Jquery.expando], otherwise it is directly jquery.expando.
Determining that the parent cache object cache--is a DOM object is the global cache object Jquery.cache, otherwise the elem itself. */
var internalkey = Jquery.expando, getbyname = typeof name = = = "String", Thiscache,
We have to handle DOM nodes and JS objects differently because ie6-7
Can ' t GC object references properly across the DOM-JS boundary
Isnode = Elem.nodetype,
Only DOM nodes need the global JQuery cache; JS Object Data is
Attached directly to the object so GC can occur automatically
Cache = Isnode? JQuery.cache:elem,
Only defining a ID for JS objects if it cache already exists allows
The code to shortcut on the same path as a DOM node with no cache
id = isnode? elem[Jquery.expando]: elem[Jquery.expando] && Jquery.expando;
/** returns directly if the Read method but the ID is empty (indicating that no data has been stored). */
Avoid doing any more work than we need to after trying to get data on
Object that has no data at all
if (!id | | (Pvt && ID &&!cache[ID] [Internalkey]) && getbyname && data = = undefined) {
Return
}
/** If the ID does not exist for which it is constructed--the DOM object is generated by the global UUID as a unique value, otherwise it is directly jquery.expando. */
if (!id) {
Only DOM nodes need a new unique ID for each element since their data
Ends up in the global cache
if (Isnode) {
elem[Jquery.expando] = id = ++jquery.uuid;
} else {
id = Jquery.expando;
}
}
/** If a child cache object cache[ID] does not exist for which an empty object is constructed-the JS kernel object of non-dom needs to introduce a Tojson attribute for its child cache object. */
if (!cache[id]) {
cache[id] = {};
Todo:this is a hack to 1.5 only. Avoids exposing jQuery
Metadata on plain JS objects when the object is serialized using
Json.stringify
if (!isnode) {
cache[id].tojson = jquery.noop;
}
}
/** if it is a call that writes more than one piece of data, the data that needs to be written is extended to the child cache object Thiscache. */
An object can is passed to Jquery.data instead of a key/value pair; This gets
Shallow copied over onto the existing cache
if (typeof name = = = "Object" | | typeof name = = "function") {
if (Pvt) {
cache[ID [Internalkey] = jquery.extend (cache[ID [internalkey], name);
} else {
cache[id] = Jquery.extend (cache[id], name);
}
}
/** determines that the child cache object thiscache--is the jquery.cache[ID of the DOM object, otherwise it is elem[ID]. */
Thiscache = cache[ID];
Internal jQuery data is stored in a separate object inside the object ' s data
Cache in order to avoid key collisions between internal data and user-defined
Data
if (Pvt) {
if (!thiscache[Internalkey]) {
thiscache[Internalkey] = {};
}
Thiscache = thiscache[Internalkey];
}
/** writes a data to the child cache object Thiscache If it is a call that writes a single piece of data. */
if (data!== undefined) {
thiscache[jquery.camelcase (name) = data;
}
Todo:this is a hack to 1.5 only. It is removed in 1.6. Users should
Not attempt to inspect the internal events object using Jquery.data, as this
Internal the data object is undocumented and subject to the change.
if (name = = = "Events" &&!thiscache[name]) {
Return thiscache[Internalkey] && thiscache[internalkey].events;
}
/** returns a data/all data if it is a call to read a single/multiple data. */
Return getbyname? thiscache[jquery.camelcase (name)]: Thiscache;
},
2 Jquery.removedata (Elem, Name, PVT/* Internal use only * *) method source code

The Removedata method only assumes the D type of the data operation, the relative function is unitary, the method internal process is similar, the difference is that when the child-independent cache object has no cached data inside, it needs to delete the independent cache object itself and the corresponding attribute of the DOM object.


Removedata:function (Elem, Name, PVT/* Internal use only * *) {
if (!jquery.acceptdata (Elem)) {
Return
}
var internalkey = Jquery.expando, Isnode = Elem.nodetype,
Jquery.data for more information
Cache = Isnode? JQuery.cache:elem,
Jquery.data for more information
id = isnode? elem[Jquery.expando]: Jquery.expando;
If there is already no cache entry to this object, there is no
Purpose in continuing
if (!cache[id]) {
Return
}
if (name) {
var Thiscache = pvt? cache[ID] [Internalkey]: cache[ID];
if (Thiscache) {
Delete thiscache[name];
If There is no data left in the cache, we want to continue
And let the cache object itself get destroyed
if (!isemptydataobject (Thiscache)) {
Return
}
}
}
Jquery.data for more information
if (Pvt) {
Delete cache[ID [Internalkey];
Don ' t destroy the parent cache unless the internal data object
Had been the only thing left in it
if (!isemptydataobject (cache[id)) {
Return
}
}
var internalcache = cache[ID [internalkey];
Browsers that fail expando deletion also refuse to delete Expandos on
The window, but it'll allow it on all other JS objects; Other browsers
Don ' t care
if (JQuery.support.deleteExpando | | cache!= window) {
Delete cache[ID];
} else {
cache[id] = NULL;
}
We destroyed the entire user cache at once because it ' s faster than
Iterating through each key and but we need to continue to persist internal
Data if it existed
if (Internalcache) {
cache[id] = {};
Todo:this is a hack to 1.5 only. Avoids exposing jQuery
Metadata on plain JS objects when the object is serialized using
Json.stringify
if (!isnode) {
cache[id].tojson = jquery.noop;
}
cache[ID [Internalkey] = Internalcache;
Otherwise, we need to eliminate "expando on" node to avoid
False lookups in the cache for entries that no longer exist
else if (Isnode) {
IE does not allow us to delete expando properties from nodes,
Nor does it have a removeattribute function on Document nodes;
We must handle all of these cases
if (JQuery.support.deleteExpando) {
Delete elem[Jquery.expando];
else if (Elem.removeattribute) {
Elem.removeattribute (Jquery.expando);
} else {
elem[Jquery.expando] = null;
}
}
},

Four internal private data/level two caching scheme

If the caller wants the cached data to be not externally accessible, the jquery data is maintained separately for the storage location of the datastore, and the internal name of the child-independent cache object is also ' JQuery. Expando ' attribute value object, which is equivalent to a level two cache scenario, the JQuery data module's caller knows how to access and store the data, and other users do not care about the data, which is the _data () method by calling ' Jquery.data (elem, name, data, true); ' Method and pass the fourth parameter Pvt to True, the Jquery.data () method has an independent logical judgment and handles private data.

The implementation of the JQuery data module is more general, i.e. it supports storing "any type" of cached data on a DOM object/kernel object, which will be used for the upper module, which can be of any type according to the intent and requirements of the upper module. For example, for the requirements of the JQuery event module, the cached data deposited on the selection DOM element is the "set of executable functions", when the data objects cached in the jquery data module function very much like the callback function storage object in the jquery deffered module. That is, it plays the role of "cartridge", which stores an event callback function queue for each DOM element event type, just as bullets with different caliber sizes are stored in their respective magazines. For other modules, the function data is not necessarily stored, and other types of data can be stored entirely according to the requirements of the module designer. The following analysis of the jquery event module will go into this topic.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.