Data Analysis of jQuery 3.0 and jquery Analysis
JQuery 3.0 was officially released in June 9, and 3.0 is also known as the next generation of jQuery. This version has been released for beta (October,) and candidate () since ). It's not easy along the way.
Document directory
I. Data Analysis
Data in jQuery 3.0 is used internally and is defined as a "class ". A total of two objects are created, datemediv and dataUser. Data has one object attribute (expando) and one class attribute (uid). There are six methods, as shown below:
Next we will explain
1. Data. uid
This is a number from 1.
2. expando
It is a combination of jQuery. expando and uid. It is used as the key of an element (such as a DOM element) and is unique. Generate jQuery. expando as follows:
jQuery.expando = "jQuery" + ( version + Math.random() ).replace( /\D/g, "" )
That is, 'jquery '+ (Version Number + random number), and remove all non-numeric values, such
"jQuery" + "3.0.0" + 0.129896303388626 == "jQuery3.0.00.129896303388626"
Remove non-numeric values
"jQuery30009423638425146147"
The internal variables datadev and dataUser in jQuery 3.0 generate expando as follows:
jQuery 300 024727210109188635 1jQuery 300 024727210109188635 2
The third part is the random number, which changes every time the refresh is performed, and the rest remains unchanged.
3. cache
The cache method binds an object to the owner for storage. The owner must meet the acceptData requirement. The cache uses this. expando as the clue key.
There are two types of owner: one is the DOM element (nodeType is 1 and 9), and the other is a common JS object. Such as text node (nodeType = 3) and comment node (nodeType = 8) are not added.
The definition of acceptData is as follows:
var acceptData = function( owner ) {// Accepts only:// - Node// - Node.ELEMENT_NODE// - Node.DOCUMENT_NODE// - Object// - Any/* jshint -W018 */return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );};
AcceptData is used in a total of three parts in 3.0, which are
If it is a DOM element, the point operator is used to assign values directly. If it is a common JS Object, the ES5 Object. defineProperty method is used, which is also the embodiment of jQuery 3.0 using the new API.
// If it is a node unlikely to be stringify-ed or looped over// use plain assignmentif ( owner.nodeType ) {owner[ this.expando ] = value;// Otherwise secure it in a non-enumerable property// configurable must be true to allow the property to be// deleted when data is removed} else {Object.defineProperty( owner, this.expando, {value: value,configurable: true} );}
Convert to the following code:
elem['jQuery3000247272101091886351'] = dataObj;var person = {name: 'John', age: 30};Object.defineProperty( person, 'jQuery3000247272101091886351', {value: dataObj,configurable: true} );
The cache method is like this. Pass in the owner, only set for the first time, return value (an empty object), and then get value and return directly.
Source code
cache: function( owner ) {// Check if the owner object already has a cachevar value = owner[ this.expando ];// If not, create oneif ( !value ) {value = {};// We can accept data for non-element nodes in modern browsers,// but we should not, see #8335.// Always return an empty object.if ( acceptData( owner ) ) {// If it is a node unlikely to be stringify-ed or looped over// use plain assignmentif ( owner.nodeType ) {owner[ this.expando ] = value;// Otherwise secure it in a non-enumerable property// configurable must be true to allow the property to be// deleted when data is removed} else {Object.defineProperty( owner, this.expando, {value: value,configurable: true} );}}}return value;},
4. set
The cache method above creates an empty object with expando as the key for the owner, and all subsequent methods will expand around this empty object, which is called a cache object, all the subsequent data is added to it. Set is to add a new attribute and data to this object. Each time a set retrieves the cache, it adds new attributes and data to it. If data is a string, add it as the key. If data is an object, traverse it and add it. Note that the crossline connector is converted into a camper, which is also compatible with H5 data-xxx.
Source code
set: function( owner, data, value ) {var prop,cache = this.cache( owner );// Handle: [ owner, key, value ] args// Always use camelCase key (gh-2257)if ( typeof data === "string" ) {cache[ jQuery.camelCase( data ) ] = value;// Handle: [ owner, { properties } ] args} else {// Copy the properties one-by-one to the cache objectfor ( prop in data ) {cache[ jQuery.camelCase( prop ) ] = data[ prop ];}}return cache;},
5. get
Get is extremely simple. If a key is transferred, the value of the key is retrieved from the cache. If no key is obtained, the entire cache is retrieved.
Source code
get: function( owner, key ) {return key === undefined ?this.cache( owner ) :// Always use camelCase key (gh-2257)owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];},
6. access
This method is real-time getter, which is also setter. The reason for its existence is that many jQuery APIs have the functions of setter and getter, such as .data).html and. text. With access, you can write much less if/else.
Getter Condition
Setter Condition
Source code
access: function( owner, key, value ) {// In cases where either://// 1. No key was specified// 2. A string key was specified, but no value provided//// Take the "read" path and allow the get method to determine// which value to return, respectively either://// 1. The entire cache object// 2. The data stored at the key//if ( key === undefined ||( ( key && typeof key === "string" ) && value === undefined ) ) {return this.get( owner, key );}// When the key is not a string, or both a key and value// are specified, set or extend (existing objects) with either://// 1. An object of properties// 2. A key and value//this.set( owner, key, value );// Since the "set" path can have two possible entry points// return the expected data based on which path was taken[*]return value !== undefined ? value : key;},
7. remove
Clear the cache object on the Bound Element (owner). You still need to get the cache through this. expando first. If the key is passed, delete the value of the specified key (the key itself is also deleted ).
Of course, jQuery API maintains existing convenience. keys can be an array, so that multiple keys can be deleted in batches. If the key is not transmitted, the entire cache is deleted. DOM and common JS objects are distinguished here. DOM objects use undefined to assign values, and JS objects use delete.
Source code
remove: function( owner, key ) {var i,cache = owner[ this.expando ];if ( cache === undefined ) {return;}if ( key !== undefined ) {// Support array or space separated string of keysif ( jQuery.isArray( key ) ) {// If key is an array of keys...// We always set camelCase keys, so remove that.key = key.map( jQuery.camelCase );} else {key = jQuery.camelCase( key );// If a key with the spaces exists, use it.// Otherwise, create an array by matching non-whitespacekey = key in cache ?[ key ] :( key.match( rnotwhite ) || [] );}i = key.length;while ( i-- ) {delete cache[ key[ i ] ];}}// Remove the expando if there's no more dataif ( key === undefined || jQuery.isEmptyObject( cache ) ) {// Support: Chrome <=35 - 45// Webkit & Blink performance suffers when deleting properties// from DOM nodes, so set to undefined instead// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)if ( owner.nodeType ) {owner[ this.expando ] = undefined;} else {delete owner[ this.expando ];}}},
8. hasData
Used to determine whether the owner has cached data. true or false is returned.
Source code
hasData: function( owner ) {var cache = owner[ this.expando ];return cache !== undefined && !jQuery.isEmptyObject( cache );}
Ii. Use of Data in jQuery
After reading all the methods of Data, the Data class is used internally in jQuery. Two objects are created: datatev and dataUser.
These two objects have a clear division of labor in 3.0.0, and datinto V can be guessed to be a combination of "data" and "private" and abbreviated as "data. That is, datatev is a private method used to serve jQuery internal methods, and dataUser is used to serve Methods publicly available to users.
The following describes the modules in which these two objects are distributed.
Click to expand the full version.
Datemediv public $. hasData $. cleanDatacloneCopyEvent queue $ (). queue $ (). _ queueHooks $ (). promise animation $ (). animate $ (). stop $ (). finishshowHide event $. event. add $. event. remove $. event. dispatch $. event. trigger other setGlobalEvaldomManipdefaultPrefilter $ (). toggleClassdataUser public $. hasData $. cleanDatacloneCopyEvent data cache $. data $. removeData $ (). data $ (). removeData other dataAttr
As you can see above, in addition to "public", datatev is used in jQuery queue, animation, event and other modules; dataUser is used in data cache and dataAttr module.
"Public" means that datemediv and dataUser are used in the three methods.
$. HasData (elem)
Used to determine whether the elem is bound to the relevant data cache. true and false are returned. false is returned only when neither datatev nor dataUser is returned.
Source code
hasData: function( elem ) {return dataUser.hasData( elem ) || dataPriv.hasData( elem );},
$. CleanData (elems)
Clear all data caches bound to elem. Of course, you need to clear data on both datainv and dataUser.
Note: although this method is publicly exposed on $, It is not introduced on the official website API. Improper use may cause serious consequences. For example, after an event (. on) is bound, the bound events will all become invalid when this method is called. Because all data in datemediv is cleared.
CloneCopyEvent (src, dest)
This is an internal method. $. clone will use it. When cloning an element, in addition to cloning a node, the data bound to the node will also be cloned. For example
var cloneNode = $.clone(elem);
Clone elem to cloneNode, and the events added to elem will also exist.
3. Comparison of 1. x. x and 2. x. x
The implementation of the data cache module varies greatly between jQuery 1.x series and 2.x series. You can compare my 11-year post
1. cache Data Structure
1. x (until 1.11.2) the cache is stored on jQuery. cache, and 2.x( including 3.x) uses an internal Data class for caching. It mainly uses two objects: datatev and dataUser. Obviously, 2.x is better. All its cached data is private and there is no risk of accidental writing, while 1.x's jQuery. the cache is public. If it is written by mistake (for example, a student takes it for granted to add a cache object to $), the consequences are unimaginable.
2. jQuery. _ data
When you see this underline, you will know that it is private (Convention). In 1.x, it is only used internally and is not provided to developers. In the example of 1.11.2, this method is used by the event module, queue module, animation module, setGlobalEval, cloneCopyEvent, fixCloneNodeIssues, domManip, showHide, defaultPrefilter, and toggleClass. 3. x is replaced by datatev and dataUser. You can compare them.
(2/3). x is obviously better than 1.x. datatev and dataUser are truly private (better encapsulation and more secure), compared with the private jQuery. _ data agreed in 1.x. Although 3.0.0 is conservative and compatible with jQuery. _ data, I believe that later versions will be removed soon.
3. refactoring
1. x is centered on $. _ data to help implement other APIs, and (2/3). x is centered on datatev/dataUser. (2/3). x extracts the Data class after code reconstruction, which is clearer.
Related:
Http://naotu.baidu.com/file/c287195ae96011f7511571a4280042c7? Token = ddb7c115786ff90f
Http://naotu.baidu.com/file/186bfe75ebe2878fa4d70856f0f33672? Token = c8b450b939e0f65c
Http://www.cnblogs.com/snandy/archive/2011/06/10/2077298.html
Http://www.cnblogs.com/snandy/p/4650599.html