JQuery. access source code analysis
Basic functions jquery.attris the underlying support provided by jquery.attr, jquery.prop, and jquery.css. A special feature in jQuery is function overloading, such as attr, which has the following kinds of overloading $ ('# box '). attr ('title') $ ('# box '). attr ('title', 'title') $ ('# box '). attr ({title: 'title', data-menu-toggle: 'dropdown'}) $ ('# box '). attr ('title', function (){....}) but looking at jQuery. in the attr code, it does not determine whether the value exists. OK, you guessed it. In access, the copied code jQuery is implemented. fn. extend ({attr: function (name, value) {return jQuery. access (this, jQuery. attr, n Ame, value, arguments. length> 1) ;}, removeAttr: function (name) {return this. each (function () {jQuery. removeAttr (this, name) ;}, prop: function (name, value) {return jQuery. access (this, jQuery. prop, name, value, arguments. length> 1) ;}}); copy the code source code analysis outline 1. first, judge whether the key value is an object. If yes, traverse the key and call jQuery recursively. access, and set the flag bit that can be called in a chain to true2. determine whether the value has been defined. If yes, it indicates a set operation. 2.1 set operation is a chain call. 2.2. If the value is not func Tion, set raw to true2.3 to determine whether the key value is null or undefined. If the key is null 2.3.1, if the value is not a function, or if the value is forcibly assigned raw to true, call fn, it may be the following call: $ ('# box '). attr (null, {abc: 'def', a: '1'}) 2.3.1 wrap fn if value is a function, change the original fn scope and parameter 2.4 If fn exists, traverse the internal elements of jQuery and perform the set operation 3. first, determine whether the set method is used. If yes, elems is returned. If the get operation is not performed (if the length inside jQuery is 0, the specified default null value is returned) source code copy code // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's Function/** attr: function (name, value) {return jQuery. access (this, jQuery. attr, name, value, arguments. length> 1) ;}, ** @ param elems jQuery's this * @ param fn function * @ param key attribute * @ param value * @ param chainable can be chained or not, if it is a get action, it is false. If it is a set action, it is true * @ param emptyGet. If jQuery does not select the returned value of the element * @ param raw value is raw data, if raw is true, it indicates that value is raw data. If raw is false, it indicates that raw is a function * @ returns {*} */access: functio N (elems, fn, key, value, chainable, emptyGet, raw) {var I = 0, length = elems. length, bulk = key = null; // bulk volume, capacity; majority, majority; bulk // Sets partition values/*** if the parameter key is an object, to set multiple attributes, traverse the parameter key and call the access method ** $ ('# box '). attr ({data: 1, def: 'addd'}); */if (jQuery. type (key) = "object") {chainable = true; // indicates that you can call for (I in key) {jQuery in a chain. access (elems, fn, I, key [I], true, emptyGet, raw );}// Sets one value/*** $ ('# box '). attr ('customvalue', 'abc') * $ ('# box '). attr ('customvalue', function (value) {}); */} else if (value! = Undefined) {chainable = true; if (! JQuery. isFunction (value) {raw = true;} if (bulk) {// if (key = null & value! = Undefined) // Bulk operations run against the entire set/*** $ ('# box '). attr (undefined, 'abc') ** jQuery. attr. call (elems, value); after the call is complete, set fn to null */if (raw) {fn. call (elems, value); fn = null ;//... when t when executing function values/*** $ ('# box '). attr (undefined, function () {}) ** fn = bulk = jQuery. attr; ** fn = function (elem, key, value) {* return jQuery. attr. call (jQuery (elem), val Ue); *} **/} else {// if the key has a value, it is easy. The bulk here is to save a variable and store fn with bulk, then encapsulate the fn call bulk = fn; fn = function (elem, key, value) {return bulk. call (jQuery (elem), value) ;}}// jQuery. access (elems, jQuery. attr,) // if fn exists, call every element, no matter whether the key has a value or not, this judgment will be taken to execute the set action if (fn) {// recursive call of for (; I <length; I ++) {fn (elems [I], key, raw? Value:/*** if the value is the original data, the value is taken. If the value is a function, the value of this function is called * $ ('# box '). attr ('abc', function (index, value) {index points to the index of the current element, and value points to oldValue ** first calls jQuery. attr (elements [I], key) obtains the current value, and then calls the incoming fn value *}); */value. call (elems [I], I, fn (elems [I], key) ;}}/ *** if chainable is true, it indicates a set method, elems * is returned. Otherwise, the get Method * 1 is returned. if bulk is true, there is no key value. Call fn to pass elems to * 2. if bulk is false, it indicates that the key has a value. Then, determine whether the element length is greater than 0*2.1. If it is greater than 0, call Use fn to input elems [0] and key. If get * 2.2 is set to 0, it indicates that there is a problem with passing the parameter. The specified null value emptyGet */return chainable? Elems: // Gets bulk? Fn. call (elems): length? Fn (elems [0], key): emptyGet;}, copy the flexSetter method in code ExtJS, which reminds me of the flexSetter method of Ext. function. for more information about flexSetter APIs, see the usage: copy the code var ele = document. getElementById ('box'); function setAttribute (name, value) {ele. setAttribute (name, value);} var flexSetAttribute = Ext. function. flexSetter (setAttribute); flexSetAttribute ('title', 'title'); flexSetAttribute ({'abc': 'otherbu Bu ', 'other': 1}); copy the code source Code copy code/*** 1. about Ext. implementation of enumerables ** the bug * var o = {toString: 111, valueOf: 222} that cannot be traversed by built-in methods such as toString and valueOf Some browsers to be compatible }; ** for (var oo in o) * {alert (oo);} **/var enumerables = [// 'hasownproperties', 'isprototypeof ', 'propertyisenumerable ', 'valueof ', 'tolocalstring', 'tostring', 'constructor']; for (I in {toString: 1}) {enumerables = null;} Ext. function = {flexSetter: function (setter) {Return function (name, value) {// return a closure var k, I; if (name! = Null) {if (typeof name! = 'String') {// if the name is not a string, it is considered as an object and the for in for (k in name) {if (name. hasOwnProperty (k) {setter. call (this, k, name [k]); // call setter one by one} if (Ext. enumerables) {for (I = Ext. enumerables. length; I --;) {k = Ext. enumerables [I]; if (name. hasOwnProperty (k) {setter. call (this, k, name [k]) ;}}} else {setter. call (this, name, value); // if it is a string, directly call} return this ;}}}; copy the code to summarize: Obviously, Ext's flexS Etter is not powerful than jQuery, but rigorous enough. jQuery. access makes a unified arrangement for the functions of setting parameters flexibly for upper layers such as prop and attr, facilitating calls and saving bits.