JQuery. Data source code and jquery source code analysis

Source: Internet
Author: User
Tags delete cache

JQuery. Data source code and jquery source code analysis

JQuery. data is the data cache system of jQuery. It is mainly used to add data for common objects or DOM elements.

1. Internal Storage Principle

This principle is very simple. The data originally to be added to the DOM element is now centrally stored in the cache set. They are linked by a number key starting from 1. In this way, the DOM elements will not be as heavy as before, and there will be no memory leakage caused by previous loop references. Now, DOM only needs to save this numeric key value. This attribute value is stored in an attribute of the DOM element. The attribute name is generated by jQuery. expando.

2 Data Constructor
Object.defineProperty( this.cache = {}, 0, {    get: function() {        return {};    }});

First, let's take a look at the Object. defineProperty function. Its function is to add an attribute to an Object or modify the features of an existing attribute. Let's take a look at the attributes in ECMAScript5.

2.1 attributes in ECMAScript5

ECMAScript5 has two attributes: data attributes and accessors attributes.

2.1.1 data attributes:

The data attribute contains the location of a data value, where the value can be read and written. There are four features used to limit its behavior.

① [[Retriable]

Whether the attribute can be deleted through delete, whether the attribute's characteristics can be modified, and whether the attribute can be changed to the accesser attribute. The default value is true.

var  obj={name:"abc"};Object.defineProperty(obj,"name",{    configurable:false});console.log(obj.name);delete obj.name;console.log(obj.name);Object.defineProperty(obj,"name",{    configurable:true});

Note that onceRetriableSetFalse. In addition, an error is reported.

② [[Enumerable]

Whether the attributes can be obtained in the for-in loop. The default value is true. ECMAScript specifies that all attributes defined by programmers are true.

③ [[Writable]

Whether the attribute value can be modified. The default value is true.

var  obj={name:"abc"};Object.defineProperty(obj,"name",{    writable:false});console.log(obj.name);obj.name="111";console.log(obj.name);

④ [[Value]

The location where the property value is located. It is obtained when the attribute value is read, and the attribute value is written here.

var  obj={name:"abc"};console.log(obj.name);Object.defineProperty(obj,"name",{    value:111});console.log(obj.name);
2.1.2 accessors

The accessor attribute does not contain the actual property value. It contains two functions (getter and setter)

① [[Get]

The function called when the attribute is read. The default value is undefined.

② [[Set]

The function called when writing an attribute. The default value is undefined.

Var obj = {}; Object. defineProperties (obj, {name: {get: function () {return obj ["_ name"] ;}, set: function (name) {if (name! = "C #") {obj ["_ name"] = name ;}}, label: {get: function () {return "You cannot change me !!! ";}}); Obj. name =" JavaScript "; console. log (obj. name); obj. label =" I want to change you !!! "; Console. log (obj. label );

The cache attribute 0 is given above, and only the get attribute is given. Therefore, the attribute cannot be assigned a value. Only available.

this.expando = jQuery.expando + Math.random();

This expando is used to store keys in the cache for DOM elements or objects. That is, it will be stored as an attribute of the DOM element.

The attribute name in the red frame is generated by the preceding statement, indicating that the div1 attribute is stored in the cache's 1 attribute.

Data.uid = 1;
This attribute indicates that the cache attribute will start from 1. Because 0 is occupied by the frozen empty JSON, it starts from 1. The next time we add an attribute to a DOM element, it will be saved in the 2 attribute of the cache. 3. Allowed element for adding attributes
Data.accepts = function( owner ) {    return owner.nodeType ?        owner.nodeType === 1 || owner.nodeType === 9 : true;};

This code is very competent. Indicates that if the owner is a DOM element, only ELEMENT_NODE and DOCUMENT_NODE can be used to add attributes. If the owner is an object, you can add attributes. 4. Prototype property 4.1 key: function (owner ){

if ( !Data.accepts( owner ) ) {    return 0;}

If the owner cannot be added with data, the system returns the 0th elements of the cache.

unlock = owner[ this.expando ];

What we get here is

If you can find this attribute from the owner, it indicates that it has previously been added with a value, that is, it already has a key in the cache.

if ( !unlock ) {    unlock = Data.uid++;    try {        descriptor[ this.expando ] = { value: unlock};        Object.defineProperties( owner, descriptor );    } catch ( e ) {        descriptor[ this.expando ] = unlock;        jQuery.extend( owner, descriptor );    }}

If no attribute is found, it indicates that the owner is added for the first time, and a key is created. This key is based on the Data uid. 1. The Data uid is a static attribute. In this way, we can record the key of the previous element and the key of this time. Add an index to the cache for the owner (DOM element or object) in the try block. There will be compatibility issues. Security issues may occur in the Android system <4, so jQuery uses the extend static method to extend the descriptor to the owner.

if ( !this.cache[ unlock ] ) {    this.cache[ unlock ] = {};}

Here, the owner assigns an Object to the key in the cache.

This key method creates attributes for the DOM element and assigns values to the corresponding key in the cache (empty object ).

The unlock is returned, that is, the key of the owner object in the cache. 4.2 set: function (owner, data, value ){

unlock = this.key( owner ),cache = this.cache[ unlock ];
The first sentence does not need to be explained. The second sentence or cachekey value. As shown in, the cache here is still {}, because no attribute has been added for div1 before.
if ( typeof data === "string" ) {    cache[ data ] = value;

Here is the code below:

$("#div1").data("name","div1");

However, when many attributes need to be set,

$("#div1").data({name:"div1",from:"0",to:"100"});

JQuery's processing method is as follows:

// Handle: [ owner, { properties } ] args} else {    // Fresh assignments by object are shallow copied    if ( jQuery.isEmptyObject( cache ) ) {        jQuery.extend( this.cache[ unlock ], data );    // Otherwise, copy the properties one-by-one to the cache object    } else {        for ( prop in data ) {            cache[ prop ] = data[ prop ];        }    }}

In fact, I personally think that I don't need to judge any more, because extend also uses the for loop to extend the data attributes to the cache.

4.3 get: function (owner, key ){
var cache = this.cache[ this.key( owner ) ];return key === undefined ? cache : cache[ key ];

The code for retrieving attributes is very simple. If the key does not exist, the cache object is returned.

4.4 access: function (owner, key, value ){

Unified Access to the get and set methods is provided here. 4.5 remove: function (owner, key ){

unlock = this.key( owner ),cache = this.cache[ unlock ];

Obtain the Data Object of the owner in the cache. this. key returns the key of the owner in the cache.

if ( key === undefined ) {    this.cache[ unlock ] = {};

If you do not specify the attribute to be deleted, jQuery deletes all data attributes of the owner.

Otherwise, judge whether the key is an array,

if ( jQuery.isArray( key ) ) {    name = key.concat( key.map( jQuery.camelCase ) );}
If it is an array, merge the key array and the array after each key is converted to a camper, that is:
$("#div1").remove(["one_key","two_key"]);

After the code above, the key is changed["One_key", "two_key","OneKey", "twoKey"]. These four attributes will be deleted later.

If the key is not an array:

camel = jQuery.camelCase( key );if ( key in cache ) {    name = [ key, camel ];} else {    name = camel;    name = name in cache ?        [ name ] : ( name.match( core_rnotwhite ) || [] );}

Also, first jump to the hump, and then determine whether the key exists. If the key does not exist, then determine whether the camping form exists. The following regular expression is used to remove spaces before and after the camping form.

After filtering out these cases, perform the delete operation:

i = name.length;while ( i-- ) {    delete cache[ name[ i ] ];}

Use delete to delete a while loop. 4.6 hasData: function (owner ){

Whether the cache contains woner data objects. 4.7 discard: function (owner ){

Delete the woner data object in the cache. 5. Create two private caches

data_user = new Data();data_priv = new Data();
Therefore, we cannot directly obtain this cache outside jQuery. Because it is a local variable of jQuery. Data_user is used by developers and data_priv is used internally by jQuery. 6. Create external interfaces (Tool methods and prototype methods)

Since the Data constructor is private to jQuery, we cannot access it outside, so we cannot directly access the previous methods. jQuery provides some interfaces here. To operate data_user and perform attribute operations on DOM elements and objects. The tool method is very simple, but it only encapsulates the data_user method. Let's take a look at the prototype method.

jQuery.fn.extend({    data: function( key, value ) {

Both the set value and the value enter the above method.

Here, we have the idea that, when setting a value, we will set a value for all the options in the selected set. If we get a value, we will only get the value of the first option.

if ( key === undefined ) {    if ( this.length ) {        data = data_user.get( elem );        if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {            attrs = elem.attributes;            for ( ; i < attrs.length; i++ ) {                name = attrs[ i ].name;                if ( name.indexOf( "data-" ) === 0 ) {                    name = jQuery.camelCase( name.slice(5) );                    dataAttr( elem, name, data[ name ] );                }            }            data_priv.set( elem, "hasDataAttrs", true );        }    }    return data;}

In row 3rd, the elem attribute in the cache has been obtained. In the following jQuery, all attributes in elem attributes are added to elem.

HasDataAttrsThe attribute is added by ourselves, because the following code only needs to be executed once. Line 3 of the Code gets all elem attributes;

This NamedNodeMap type is rarely used directly. It is "dynamic" like NodeList and HTMLCollection. Each item in the NamedNodeMap set is of the Attr type. The Attr object has three attributes: name, value, and specified.

In the for loop below, check whether the name attribute contains"Data -"Prefix. If yes, remove it and convert the remaining part into a camper.

If the key does not exist, all attribute values of the first option in the selected set are obtained. Elem indicates the first option.

if ( typeof key === "object" ) {    return this.each(function() {        data_user.set( this, key );    });}
Corresponding form:
$("#div1").remove(["one_key","two_key"]);

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.