Heim > Web-Frontend > js-Tutorial > Hauptteil

Detaillierte Erläuterung der Setter- und Getter-Modi von jQuery 3.0

高洛峰
Freigeben: 2017-01-03 17:13:33
Original
1110 Leute haben es durchsucht

JQuerys Setter/Getter teilen sich eine Funktion und ihre Bedeutung wird dadurch angezeigt, ob Parameter übergeben werden sollen. Einfach ausgedrückt: Wenn Parameter übergeben werden, handelt es sich um einen Setter, und wenn keine Parameter übergeben werden, handelt es sich um einen Getter.

In Programmiersprachen ist es nicht ungewöhnlich, dass eine Funktion mehrere Bedeutungen hat, wie z. B. Funktionsüberladung: Eine Gruppe von Funktionen mit demselben Funktionsnamen und unterschiedlichen Parameterlisten, diese Gruppe von Funktionen ist wird als überladene Funktion bezeichnet. Der Vorteil der Überladung besteht darin, dass sie die Anzahl der Funktionsnamen reduziert, eine Verschmutzung des Namensraums vermeidet und sich auch sehr positiv auf die Lesbarkeit des Programms auswirkt.

Funktionsüberladung spiegelt hauptsächlich zwei Aspekte wider. Die gleiche Anzahl von Parametertypen kann auch als Funktionsüberladung bezeichnet werden Man nennt es Funktionsüberladung. Beachten Sie, dass Überladung nichts mit dem Rückgabewert der Funktion zu tun hat.

Wenn Sie eine Funktionsüberladung simulieren möchten, können Sie dies aufgrund der schwachen Typeigenschaften von JS nur mit der zweiten Methode tun: der Anzahl der Parameter. Daher ist das Argumentobjekt innerhalb der Funktion sehr wichtig.

Das Folgende ist ein Beispiel

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

doAdd realisiert drei Bedeutungen durch Überladen, um die Anzahl der Parameter der Funktion zu bestimmen. Wenn argsLength 0 ist, gibt es 0 direkt zurück , das Argument wird zu 10 addiert; wenn argsLength 2 ist, werden die beiden Argumente addiert.

Setter/Getter kann mithilfe der Funktionsüberladungsfunktion implementiert werden

function text() {
var elem = this.elem
var argsLength = arguments.length
if (argsLength === 0) {
return elem.innerText
} else if (argsLength === 1) {
elem.innerText = arguments[0]
}
}
Nach dem Login kopieren

Oben wird kurz die Funktionsüberladung und ihre Verwendung zur Implementierung von Setter/Getter erläutert. Das heißt, der „Wertnehmer“ und der „Zedent“ werden zu einem zusammengefasst. Ob ein Wert abgerufen oder zugewiesen werden soll, wird durch die Parameter der Funktion bestimmt. Viele jQuery-API-Designs nutzen dieses Muster intensiv.

Die folgende Abbildung fasst alle APIs zusammen, die dieses Muster in jQuery verwenden, mit insgesamt 14 Funktionen

jQuery 3.0 的 setter和getter 模式详解

Alle diese Funktionen hängen intern voneinander ab Funktionszugriff: Man kann ohne Übertreibung sagen, dass der Zugriff der Kern all dieser Funktionen und der Kern der Setter/Getter-Implementierung ist. Das Folgende ist der Quellcode dieser Funktion. Es handelt sich um eine private Funktion, die nicht extern aufgerufen werden kann.

jQuery 3.0 的 setter和getter 模式详解

Der Quellcode des Zugriffs lautet wie folgt

// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var 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;
};
Nach dem Login kopieren

Der Kommentar dieser Funktion erwähnt: Dies ist eine multifunktionale Funktion, die zum Abrufen von und verwendet wird Legen Sie eine Sammlung von Elementattributen und -werten fest. value kann eine ausführbare Funktion sein. Diese Funktion umfasst insgesamt weniger als 60 Codezeilen. Von oben nach unten gelesen, besteht das erste if darin, mehrere Werte festzulegen, und ist ein rekursiver Aufruf. Ohne diesen rekursiven Aufruf umfasst der Code zum Festlegen eines einzelnen Werts weniger als 50 Zeilen. Der Schreibstil ist sehr prägnant und lesbar.

Um die Zugriffsfunktion zu verstehen, habe ich zwei Diagramme gezeichnet

Die beiden Hauptzweige innerhalb des Zugriffs

jQuery 3.0 的 setter和getter 模式详解

Der interne Ausführungsprozess des Zugriffs

jQuery 3.0 的 setter和getter 模式详解

Die durch den Zugriff definierten formalen Parameter verfügen über 7

1.elems-Elementsammlung, die tatsächlich übergeben wird Beim Aufruf ist dies das jQuery-Objekt. Wir wissen, dass das jQuery-Objekt selbst eine Sammlung mit einer Längeneigenschaft und einem Index ist. Muss passieren.

2.fn implementiert die Setter/Getter-Funktion, was bedeutet, dass diese Funktion Bedingungen haben muss, um zu bestimmen, welcher Teil ein Setter und welcher Teil ein Getter ist. Muss passieren.

3.key Beispielsweise sollten die Methoden attr und prop den Wert which key übergeben, festlegen oder abrufen. Einige müssen nicht übergeben werden, werden jedoch für Platzhalterzwecke durch null ersetzt, z. B. Text- und HTML-Methoden. Optional.

4.value sollte nur übergeben werden, wenn es sich um einen Setter handelt, d. h. wenn der Wert undefiniert ist, handelt es sich um einen Getter, andernfalls handelt es sich um einen Setter. Optional.

5.chainable Wenn true, wechselt es in den Setter-Modus und gibt ein jQuery-Objekt zurück. false, um in den Getter-Modus zu wechseln. Wird beim Aufruf in arguments.length oder arguments.length>1 übergeben.

6.emptyGet Wenn das jQuery-Objekt leer ist, ist das zurückgegebene Ergebnis standardmäßig undefiniert und beim Aufruf der Datenmethode wird null übergeben.

7.raw Wenn value ein Funktionstyp ist, ist raw falsch, andernfalls ist es wahr.

Wie oben erwähnt, ist der Zugriff der Kern aller Setter/Getter-Funktionen in jQuery. Mit anderen Worten: Alle 14 Setter/Getter-Funktionen rufen den Zugriff intern auf. Aus diesem Grund hat der Zugriff 7 Parameter und viele Zweige. Weil es mit vielen Bedingungen klarkommen muss. Aber alle diese Setter/Getter haben viel ähnlichen Code und extrahieren am Ende eine gemeinsame Funktion.

Um das Verständnis zu erleichtern, habe ich die Zugriffsaufrufe wie folgt klassifiziert, um unser Verständnis zu erleichtern.

1. Beim Aufruf von Access wird der dritte Parameterschlüssel als Null übergeben, nämlich die Text-/HTML-Methode

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 );
},
Nach dem Login kopieren

Das Diagramm zeigt, wo diese beiden Methoden innerhalb von Access ausgeführt werden

jQuery 3.0 的 setter和getter 模式详解

为什么 key 传 null,因为 DOM API 已经提供了。text 方法使用 el.innerText 设置或获取;html 方法使用 innerHTML 设置或获取(这里简单说,实际还有一些异常处理)。

2. 与第一种情况相反,调用 access 时 key 值传了且不为 null。除了 text/html 外的其它 setter 都是如此

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 methods
jQuery.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 methods
jQuery.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&#39;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 );
},
Nach dem Login kopieren

图示这些方法在 access 内部执行处

jQuery 3.0 的 setter和getter 模式详解

更多jQuery 3.0 的 setter和getter 模式详解相关文章请关注PHP中文网!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!