Explanation of setter and getter modes in jQuery3.0

Source: Internet
Author: User
This article mainly introduces the detailed information about setter and getter modes of jQuery3.0, which is very good and has reference value. If you need it, you can refer to setter/getter of jQuery to share a function, indicates whether to pass the parameter. To put it simply, the parameter is a setter, and the parameter is not a getter.

A function has multiple meanings and is not uncommon in programming languages. For example, function overloading: A group of functions with the same function name and different parameter lists are called overload functions. The advantage of overload is that it reduces the number of function names and avoids the pollution of namespace, which is also beneficial to the readability of the program.

Function overloading mainly involves two aspects: one is the parameter type and the same number of parameter types, which can be called function overloading; the other is the number of parameters. Different numbers are also called function overloading. Note that the overload is irrelevant to the return value of the function.

Due to weak JS features, to simulate function overloading, you can only use the second method: number of parameters. Therefore, the arguments object in the function is very important.

The following is an example

function doAdd() {var argsLength = arguments.lengthif (argsLength === 0) {return 0} else if (argsLength === 1) {return arguments[0] + 10} else if (argsLength === 2) {return arguments[0] + arguments[1]}}doAdd() // 0doAdd(5) // 15doAdd(5, 20) // 25

DoAdd implements three meanings by judging the number of parameters of the function. When argsLength is 0, 0 is directly returned; When argsLength is 1, this parameter is added to 10; when argsLength is 2, the two parameters are added.

You can use the function overload feature to implement setter/getter

function text() {var elem = this.elemvar argsLength = arguments.lengthif (argsLength === 0) {return elem.innerText} else if (argsLength === 1) {elem.innerText = arguments[0]}}

The above briefly explains the function overload and uses it to implement setter/getter. That is, the "valuer" and "value assignment" are integrated. Whether it is a value or a value is determined by the function parameters. This mode is widely used in many API designs of jQuery.

Summarizes all the APIS using this mode in jQuery, a total of 14 Functions

The source code of access is as follows:

// Multifunctional method to get and set values of a collection// The value/s can optionally be executed if it's a functionvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {  var i = 0,    len = elems.length,    bulk = key == null;  // Sets many values  if ( jQuery.type( key ) === "object" ) {    chainable = true;    for ( i in key ) {      access( elems, fn, i, key[ i ], true, emptyGet, raw );    }  // Sets one value  } else if ( value !== undefined ) {    chainable = true;    if ( !jQuery.isFunction( value ) ) {      raw = true;    }    if ( bulk ) {      // Bulk operations run against the entire set      if ( raw ) {        fn.call( elems, value );        fn = null;      // ...except when executing function values      } else {        bulk = fn;        fn = function( elem, key, value ) {          return bulk.call( jQuery( elem ), value );        };      }    }    if ( fn ) {      for ( ; i < len; i++ ) {        fn(          elems[ i ], key, raw ?          value :          value.call( elems[ i ], i, fn( elems[ i ], key ) )        );      }    }  }  return chainable ?    elems :    // Gets    bulk ?      fn.call( elems ) :      len ? fn( elems[ 0 ], key ) : emptyGet;};

This function is a multi-function used to obtain and set the attributes and values of a set element. Value can be an executable function. This function contains less than 60 lines of code. From top to bottom, the first if is to set multiple value values, which is a recursive call. When this recursive call is done, less than 50 lines of code are set for a single value. It is concise and readable.

To understand the access function, I drew two figures.

Two main branches in access

For ease of understanding, I classify access calls to the following categories for ease of understanding.

1. When access is called, the key value of the third parameter is null, which is the text/html method.

text: function( value ) {  return access( this, function( value ) {    return value === undefined ?      jQuery.text( this ) :      this.empty().each( function() {        if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {          this.textContent = value;        }      } );  }, null, value, arguments.length );},html: function( value ) {  return access( this, function( value ) {    var elem = this[ 0 ] || {},      i = 0,      l = this.length;    if ( value === undefined && elem.nodeType === 1 ) {      return elem.innerHTML;    }    // See if we can take a shortcut and just use innerHTML    if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&      !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {      value = jQuery.htmlPrefilter( value );      try {        for ( ; i < l; i++ ) {          elem = this[ i ] || {};          // Remove element nodes and prevent memory leaks          if ( elem.nodeType === 1 ) {            jQuery.cleanData( getAll( elem, false ) );            elem.innerHTML = value;          }        }        elem = 0;      // If using innerHTML throws an exception, use the fallback method      } catch ( e ) {}    }    if ( elem ) {      this.empty().append( value );    }  }, null, value, arguments.length );},

The two methods are executed inside access

2. In contrast to the first case, the key value is passed when access is called and is not null. This is true for other Setters except text and html.

attr: function( name, value ) {  return access( this, jQuery.attr, name, value, arguments.length > 1 );},prop: function( name, value ) {  return access( this, jQuery.prop, name, value, arguments.length > 1 );},// Create scrollLeft and scrollTop methodsjQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {  var top = "pageYOffset" === prop;  jQuery.fn[ method ] = function( val ) {    return access( this, function( elem, method, val ) {      var win = getWindow( elem );      if ( val === undefined ) {        return win ? win[ prop ] : elem[ method ];      }      if ( win ) {        win.scrollTo(          !top ? val : win.pageXOffset,          top ? val : win.pageYOffset        );      } else {        elem[ method ] = val;      }    }, method, val, arguments.length );  };} );css: function( name, value ) {  return access( this, function( elem, name, value ) {    var styles, len,      map = {},      i = 0;    if ( jQuery.isArray( name ) ) {      styles = getStyles( elem );      len = name.length;      for ( ; i < len; i++ ) {        map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );      }      return map;    }    return value !== undefined ?      jQuery.style( elem, name, value ) :      jQuery.css( elem, name );  }, name, value, arguments.length > 1 );}// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methodsjQuery.each( { Height: "height", Width: "width" }, function( name, type ) {  jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },    function( defaultExtra, funcName ) {    // Margin is only for outerHeight, outerWidth    jQuery.fn[ funcName ] = function( margin, value ) {      var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),        extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );      return access( this, function( elem, type, value ) {        var doc;        if ( jQuery.isWindow( elem ) ) {          // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)          return funcName.indexOf( "outer" ) === 0 ?            elem[ "inner" + name ] :            elem.document.documentElement[ "client" + name ];        }        // Get document width or height        if ( elem.nodeType === 9 ) {          doc = elem.documentElement;          // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],          // whichever is greatest          return Math.max(            elem.body[ "scroll" + name ], doc[ "scroll" + name ],            elem.body[ "offset" + name ], doc[ "offset" + name ],            doc[ "client" + name ]          );        }        return value === undefined ?          // Get width or height on the element, requesting but not forcing parseFloat          jQuery.css( elem, type, extra ) :          // Set width or height on the element          jQuery.style( elem, type, value, extra );      }, type, chainable ? margin : undefined, chainable );    };  } );} );data: function( key, value ) {  var i, name, data,    elem = this[ 0 ],    attrs = elem && elem.attributes;  // Gets all values  if ( key === undefined ) {    if ( this.length ) {      data = dataUser.get( elem );      if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {        i = attrs.length;        while ( i-- ) {          // Support: IE 11 only          // The attrs elements can be null (#14894)          if ( attrs[ i ] ) {            name = attrs[ i ].name;            if ( name.indexOf( "data-" ) === 0 ) {              name = jQuery.camelCase( name.slice( 5 ) );              dataAttr( elem, name, data[ name ] );            }          }        }        dataPriv.set( elem, "hasDataAttrs", true );      }    }    return data;  }  // Sets multiple values  if ( typeof key === "object" ) {    return this.each( function() {      dataUser.set( this, key );    } );  }  return access( this, function( value ) {    var data;    // The calling jQuery object (element matches) is not empty    // (and therefore has an element appears at this[ 0 ]) and the    // `value` parameter was not undefined. An empty jQuery object    // will result in `undefined` for elem = this[ 0 ] which will    // throw an exception if an attempt to read a data cache is made.    if ( elem && value === undefined ) {      // Attempt to get data from the cache      // The key will always be camelCased in Data      data = dataUser.get( elem, key );      if ( data !== undefined ) {        return data;      }      // Attempt to "discover" the data in      // HTML5 custom data-* attrs      data = dataAttr( elem, key );      if ( data !== undefined ) {        return data;      }      // We tried really hard, but the data doesn't exist.      return;    }    // Set the data...    this.each( function() {      // We always store the camelCased key      dataUser.set( this, key, value );    } );  }, null, value, arguments.length > 1, null, true );},

The following figure shows how these methods are executed inside access.

For more details about the setter and getter modes of jQuery 3.0, please follow the PHP Chinese network!

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.