jquery Source Code Analysis: jquery data caching mechanism detailed 1

Source: Internet
Author: User
Tags instance method delete cache

There are three ways to add data in jquery, $ (). attr (), $ (). Prop (), $ (). Data (). However, the previous two types are used to add attribute values to the element, only for a small amount of data, such as: Title,class,name, etc. The data method is the most important method of the jquery caching mechanism, which is suitable to be added in the case of JSON.

Why do we use the caching mechanism system in jquery? Because DOM elements and JS objects are referenced to each other, memory leaks are caused in most browsers. To solve this problem, jquery wrote a caching mechanism system. As an example:

var div = document.getElementById ("Div1");

var obj = {};

Div.name = obj;

Obj.age = div;

The above code, the DIV element refers to the JS object Obj,obj references the div element, referencing each other, causing a memory leak.

$ (). attr (), $ (). Prop () These two methods have the potential to refer to each other when mounting a JS object on an element. For example: $ ("#div1"). attr (name,obj), obj refers to div1 elements, and if you mount a string or a number, there is no cross-referencing problem. However, the data method does not appear this way regardless of what is mounted.

The principle of data:

When you call $ ("#div1"). Data ("name", obj), a custom attribute xxx is added to the element Div, whose value is a cumulative unique value in jquery, here is 1, and then the global variable cache object of jquery is added 1 this property, Its property value is a JSON, the JSON object will have the Name property, the property value is the Obj object. When you call $ ("body"). Data ("Age", obj), the xxx attribute is added to the BODY element, its value is 2, and then the 2 attribute is added to the cache object, and its property value is a JSON, and this JSON will have the age attribute. The property value is obj.

As can be seen from the above, the name,age stored in the cache, and their values, are not directly related to the elements, so there is no cross-referencing phenomenon, they are through a custom property and custom attribute values (the unique number value in jquery, The number on the element is not associated with the result of referencing each other. Next, let's look at how jquery's caching system is used:

How the instance method is used:

$ ("#div1"). Data ("name", "Hello"); //Set the name data value for the element div

$ ("#div1"). Data ("name"); //Take the name value of the element div setting

$ ("#div1"). Removedata ("name"); //Delete the name data value of the element div

How static methods are used:

$.data (Document.body, "age", 30); //Set the age data value for the element body

$.data (Document.body, "age"); //Take the age value of the element body setting

$.removedata (Document.body, "age"); //Delete element body's age data value

$.hasdata (Document.body, "age"); //element body whether the age data value is set

Finally, let's take a look at the source code, jquery's caching system is actually implemented using the Date object:

function Data () {
Object.defineproperty (This.cache = {}, 0, {
Get:function () {     //added a 0 property to the cache object whose property value could not be modified
return {};

});

//Let's explain how this works, for example: var obj = {Name: " Hello "};obj.name =" Chaojidan "; This is where you can modify the value of the Obj.name property. But if we add this line of code Object.freeze (obj) before obj.name = "Chaojidan", then Obj.name is still "hello" and will not change to "Chajidan". The Object.defineproperty method here is the same as the effect of the Object.freeze method. For example: var obj = {name: "Hello"};object.defineproperty (Obj,0,{get:function () {return {};}}  ),
This method receives three parameters, the first parameter is the object we want to set obj, the second argument is the property name, that is, we added 0 to the Obj object, and the third parameter is the property value of the 0 property. So at this point obj = {name: "Hello", 0:{get:function () {return {};}}  }; and then you obj[0] = 123; At this point obj[0] does not change to 123, but the Get method returns the value {} (because the 0 property value JSON object has only the Get method, there is no set method, the Get method is used to get, set method is used for setting.) If there is a set method, you can set the value of Obj[0].

This.expando = Jquery.expando + math.random (); //The only identifier is that when you add data to an element node, a custom attribute is added to the element node, and the name of the custom property is the value of This.expando.
}

Data.uid = 1; //is a cumulative number, which is the unique property name on this side of the cache object. When the second element adds data, its property name in the cache object is 2, and the first element's property name is 1, and the third element's property name is 3 ....

data.accepts = function (owner) { //If it is an element node, the element must be elements or document, and no other element node can add data to the cache object
Return owner.nodetype? owner.nodetype = = 1 | | Owner.nodetype = = = 9:true;
};

Data.prototype = {
Key:function (owner) { //allocation map, which corresponds to attribute object one by one in an element and a cache object
if (! Data.accepts (owner)) { //determines if this element can add data to the cache, and if it can be added, it executes the following code, returning a unique cumulative number, which is the data.uid++ above. If it cannot be added, it returns 0 directly. And this 0 attribute is not able to set the data, can only get.
return 0;
}

var descriptor = {},
unlock = owner[This.expando];

if (!unlock) { //If the custom property value is not set before this element node, enter the IF statement setting
unlock = data.uid++; //Assign a unique number value that is the ID.

try {
descriptor[This.expando] = {Value:unlock}; //descriptor = {this.expando: {value:data.uid++}}
Object.defineproperties (owner, descriptor); //This method means that the DefineProperty operation is performed on each property in the Descriptor object. This code can be written as Object.defineproperty (owner, this.expando,{value:data.uid++}); Add the This.expando property name (custom attribute) to the owner element node, whose value is the property value of value data.uid++ (that is, the unique number value), and this property value cannot be modified, only obtained. Some browsers do not support this method, so the catch

} catch (e) {
descriptor[This.expando] = unlock; //descriptor = {This.expando:ID}
Jquery.extend (owner, descriptor); //Add this custom attribute This.expando to the element node, and set the value to ID. That is, an attribute is added to the element This.expando (custom attribute) = data.uid++ (a unique number value);
}
}

if (!this.cache[unlock]) { //Set the ID's property name in the Cache object, its property value is {}
this.cache[unlock] = {};
}

return unlock;    // When the second data is added to the same element, the owner[This.expando] is returned directly, so the value of the custom attribute for the same element is the same.   

Set:function (owner, data, value) {//add data value to the cache object
Var prop,
unlock = This.key (owner),   //first find this ID (all-in-one ...)
cache = this.cache[unlock]; &nbs P //the JSON object that found this property name ID in the cache

if (typeof data = = = "string") {
cache[data] = value; //If you add a string, add it directly to the JSON object

} else { //If this is the case: $.data (document.body,{"age": +, "job": "It"})
if (jquery.isemptyobject (cache)) {
jquery.extend (this.cache[unlock], data);
} else {
For (prop in data) {
cache[Prop] = data[prop];
}
}
}
return cache;
},
get:function (owner, key) { ///go to cache object to get a value
var cache = this.cache[This.key (owner)];

return key = = undefined cache:cache[key]; If you do not pass in key, all data added on this element is returned, and if you pass in key, only the property value of the key property is returned.
},
Access:function (owner, key, value) { //The Get and set are consolidated, depending on the number of arguments, whether it is a get or set operation
var stored;
if (key = = = Undefined | | (key && typeof key = = = "string") && value = = = undefined)) {

stored = this.get (owner, key);

Return stored!== undefined stored:this.get (owner, Jquery.camelcase (key));
}

This.set (owner, key, value);

return value!== undefined? Value:key;
},
Remove:function (owner, key) { //delete the value in the cache object
var i, name, Camel,unlock = This.key (owner), cache = this.cache[unlock];

if (key = = = undefined) { //If the key is not passed in, the entire data of this element is deleted
this.cache[unlock] = {};

} else {
if (Jquery.isarray (key)) { //If it is an array, it is necessary to delete multiple attribute values, such as: $.removedata (document.body,["age", "job", "All-name"]), n AME = ["Age", "job", "All-name", "Allname"],map method please refer to http://www.cnblogs.com/chaojidan/p/4142338.html.
name = Key.concat (Key.map (jquery.camelcase));
} else {
camel = jquery.camelcase (key); //If a value is passed in, first turn this value into hump form
If (key in cache) { //This value is in the cache
name = [key, Camel]; //If in, name = [key, Key's hump notation (if no hump is written, then key)]
} else { //If key is not in cache
name = Camel; //First check key hump writing in the cache, if the key is not the camel's writing is not in the cache, see if the name is separated by a space string, such as: "Age Job", then use regular match, return [Age,job]
name = name in cache? [Name]: (Name.match (core_rnotwhite) | | [] );
}
}

i = name.length;
While (i--) { //delete the corresponding property value in the cache
Delete cache[name[i];
}
}
},
Hasdata:function (owner) { //Determine if the cache object has this attribute
return!jquery.isemptyobject (
this.cache[owner[This.expando] | | {} //ELEMENT nodes have data in the cache system
);
},
Discard:function (owner) { //delete all data from the element node in the cache object at once
if (owner[This.expando]) {
Delete this.cache[owner[This.expando]];
}
}
};

The above is the data construction method implementation of the source code parsing, with this construction method, we can instantiate the data object, through the data instance object to manipulate the jquery caching mechanism.

The instance object data can invoke all the methods and properties in the data prototype object, so as soon as new data is available, the new data object can be used for the caching of jquery.

In the next lesson, we will explain how jquery uses the new data object to manipulate it.

Come on!

jquery Source Code Analysis: jquery data caching mechanism detailed 1

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.