VorwortWie wir alle wissen, dienen die Funktionen „call“, „apply“ und „bind“ dazu, den Umfang zu „ändern“, aber das Internet ist in Bezug auf diese „Änderung“ vage und liefert keine detaillierten Erklärungen. Bedeutet „ändern“ das direkte Ersetzen des Umfangs? Wer ersetzt wen? Wie wird die Wirkung erzielt? Wer diese Fragen nicht klar versteht, wird sich diese wahrscheinlich auch bei der handschriftlichen Umsetzung nicht lange merken können. Daher stellt dieser Artikel die Verwendung von „call“, „apply“ und „bind“ sowie die jeweiligen Implementierungsprinzipien vor. AnrufDie Methode call() ruft eine Funktion mit einem angegebenen this-Wert und einem oder mehreren einzeln angegebenen Argumenten auf. Das heißt, Sie können den This-Zeiger der aktuellen Funktion ändern und die aktuelle Funktion ausführen lassen. VerwendungFunktion Spaß() { console.log(dieser.Name, Argumente) } let obj = { name: 'clying' } Spaß.call(Objekt, 'deng', 'deng') // klicken [Argumente] { '0': 'deng', '1': 'deng' } erreichenDie Implementierung von „call“ und „apply“ besteht darin, die Funktion in eine Eigenschaft des Literalobjekts „obj“ einzufügen, sodass diese in der Funktion auf das Literalobjekt „obj“ verweist. Eine einfache Implementierungsversion:Function.prototype.mycall = Funktion (Kontext) { Kontext = (Kontext == null || Kontext == undefiniert) ? Fenster : neues Objekt(Kontext) Kontext.fn = dies Kontext.fn() lösche context.fn } Fügen Sie dem Funktionsprototyp die Methode mycall hinzu und erstellen Sie ein Kontextobjekt context. Wenn das übergebene Objekt nicht existiert, zeigt es auf das globale Fenster. Durch Hinzufügen des fn-Attributs zum Kontext verweist das fn des Kontexts auf die Funktion fun, die die Methode aufruft und fun ausführt. Löschen Sie das Attribut fn, nachdem die Ausführung abgeschlossen ist. Es ist notwendig, zuerst die übergebenen Parameter abzurufen, dann wird daraus ein Zeichenfolgenarray. Die Ausführungsmethode verwendet die Funktion eval, die die Zeichenfolge berechnet, den darin enthaltenen Code ausführt und das Berechnungsergebnis zurückgibt. Verbesserte Version:Übergeben Sie Parameter an den Aufruf. Function.prototype.mycall = Funktion (Kontext) { Kontext = (Kontext == null || Kontext == undefiniert) ? Fenster : neues Objekt(Kontext) Kontext.fn = dies lass arr = [] für (lass i = 1; i < Argumente.Länge; i++) { arr.push('Argument[' + i + ']') // ["Argumente[1]", "Argumente[2]"] } let r = eval('context.fn(' + arr + ')') // Führe die Funktion fun aus und übergebe den Parameter delete context.fn Rückkehr r } Darüber hinaus können Aufrufe auch durch Dekonstruktionssyntax implementiert werden. Function.prototype.mycall = Funktion (Kontext, ...Argumente) { Kontext = (Kontext == null || Kontext == undefiniert) ? Fenster : neues Objekt(Kontext) Kontext.fn = dies Kontext.fn(...args) lösche context.fn } Wenn Sie die Aufrufmethode mehrmals aufrufen möchten, können Sie context.fn(...args) in einer Variablen speichern und am Ende zurückgeben. Function.prototype.mycall = Funktion (Kontext, ...Argumente) { Kontext = (Kontext == null || Kontext == undefiniert) ? Fenster : neues Objekt(Kontext) Kontext.fn = dies lass r = Kontext.fn(...args) lösche context.fn Rückkehr r } anwendenÄhnlich wie die Call-Methode empfängt die Call-Methode eine Parameterliste, während die Apply-Methode ein Array mit mehreren Parametern empfängt. VerwendungLegen Sie dies in der Funktion so fest, dass es auf den ersten übergebenen Parameter verweist und der zweite Parameter ein Array ist. Funktion Spaß() { console.log(dieser.Name, Argumente); } lass obj = { Name: 'clying' } Spaß.anwenden(Objekt, [22, 1]) // Argumente(2) [22, 1] erreichenImplementieren Sie selbst eine Apply-Methode myapply. Die Implementierungsmethode ähnelt dem Aufruf, beim Empfangen von Parametern können Sie jedoch ein Argument als zweiten übergebenen Parameter verwenden. Beurteilen Sie direkt, ob der zweite Parameter nicht übergeben wird, und führen Sie die Funktion direkt aus. Andernfalls verwenden Sie eval, um die Funktion auszuführen. Function.prototype.myapply = Funktion (Kontext, Argumente) { Kontext = (Kontext == null || Kontext == undefiniert) ? Fenster : neues Objekt(Kontext) Kontext.fn = dies if(!args) returniere Kontext.fn() lass r = eval('Kontext.fn('+args+')') lösche context.fn Rückkehr r } bindenDie Methode bind() erstellt eine neue Funktion und wird nicht automatisch ausgeführt. Sie müssen bind() manuell aufrufen. Dieser Wert der neuen Funktion wird als erster Parameter von bind() zugewiesen und die verbleibenden Parameter werden als Parameter der neuen Funktion verwendet, wenn diese aufgerufen wird. VerwendungBinden Sie obj an this der Fun-Funktion. Die Fun-Funktion kann die Eigenschaften innerhalb von obj und die übergebenen Variablen verwenden. Funktion Spaß() { console.log(dieser.Name, Argumente); } lass obj = { Name: 'clying' } sei b = fun.bind(obj,2) b(3) // Argumente(2) [2, 3] Darüber hinaus kann die durch die Bind-Methode gebundene Funktion auch eine neue Instanz erstellen, dies wird sich jedoch zu diesem Zeitpunkt ändern. Verbesserte Version – Verwendung von Prototyp-Eigenschaften: Funktion Spaß() { console.log(dieser.Name, Argumente); } lass obj = { Name: 'clying' } Spaß.Prototyp.Alter = 23 sei b = fun.bind(obj, 3) lass Instanz = neues b(4) Konsole.log(Instanz.Alter); //undefinierte Argumente(2) [3, 4] // dreiundzwanzig erreichen Basisversion:Die Implementierung von Bind kann auf Call und Apply basieren. Da „Bind“ nicht sofort ausgeführt wird, kann es eine Funktion zurückgeben, damit der Benutzer es manuell ausführen kann. Verwenden Sie in der zurückgegebenen Funktion „call“ oder „apply“, um das angegebene this-Objekt und die angegebenen Parameter zu übergeben. Anwenden von Geräten binden Function.prototype.mybind = Funktion (Kontext) { lass das = dies let bindargs = Array.prototype.slice.call(Argumente, 1) Rückgabefunktion () { let args = Array.prototype.slice.call(Argumente) gib das zurück.anwenden(Kontext, Bindargs.concat(Argumente)) } } Die Apply-Methode wird hauptsächlich zum Abrufen und Verarbeiten der von Bind übergebenen Parameter sowie der vom Benutzer beim Ausführen der Funktion übergebenen Parameter verwendet. Verwenden Sie die Slice-Methode der Array-Prototypmethode, um die erforderlichen Parameter abzufangen. Beim Abrufen der per Bind übergebenen Parameter müssen Sie mit dem Abfangen beim zweiten Parameter beginnen, die Startposition ist also 1. Aufruf implementiert binden Function.prototype.mybind = Funktion (Kontext, ...args1) { lass das = dies Rückgabefunktion (...args2) { gib das zurück.call(Kontext, ...args1, ...args2) } } Um den Aufruf zu implementieren, verketten Sie die Parameter einfach an das Ende der Aufrufmethode. Verbesserte Version:Zusätzlich zur Änderung des Zeigers ermöglicht Bind den Benutzern auch die Übergabe von Parametern nach Bind und ermöglicht es den Benutzern auch, bei der Ausführung des Befehls Parameter zu übergeben. Sie können die Ausführungsfunktion auch neue Operationen ausführen lassen. Wenn zum Erstellen eines Werts eine gebundene Funktion verwendet wird, wird das ursprünglich bereitgestellte „this“ ignoriert. Die bereitgestellte Parameterliste wird jedoch weiterhin vor der Parameterliste eingefügt, wenn der Konstruktor aufgerufen wird. anwenden Function.prototype.mybind = Funktion (Kontext) { lass das = dies let bindargs = Array.prototype.slice.call(Argumente, 1) Funktion fBind() { let args = Array.prototype.slice.call(Argumente) // Wenn new verwendet wird, wird dies auf die fBind-Instanz verweisen. Wenn dies nicht die aktuelle Instanz ist, verwenden Sie das Kontextobjekt return that.apply(this instanceof fBind ? this : context, bindargs.concat(args)) } Rückgabewert fBind } Beachten Sie bei der Verwendung des new-Operators, dass Sie den Zeiger von this ändern müssen. Wenn dieser new ist, dann zeigt this auf die Instanz. Wenn new nicht verwendet wird, dann zeigt es auf den ersten Parameter, der aktuell von bind übergeben wird. Darüber hinaus beinhaltet es auch die Möglichkeit, der ursprünglichen Funktion eigene Methodenattribute hinzuzufügen. Wenn Sie die eigene Prototypmethode von fun verwenden möchten, müssen Sie auch fBind.prototype = this.prototype verwenden, um eine gemeinsame Nutzung des Prototyps zu erreichen. Bei der gemeinsamen Nutzung von Eigenschaftswerten von Referenztypen ist jedoch eine Änderung nicht möglich, ohne andere Instanzen zu ändern (wenn eine Prototypmethode oder -eigenschaft geändert wird, werden alle Referenzen geändert). Function.prototype.mybind = Funktion (Kontext) { lass das = dies let args = Array.prototype.slice.call(Argumente, 1) function fBind() { // Führe die Bind-Funktion aus let bindargs = Array.prototype.slice.call(arguments) gib das zurück.anwenden(diese Instanz von fBind? dies: Kontext, args.concat(bindargs)) } function Fn(){} // Die Prototypen der beiden Klassen werden nicht gemeinsam genutzt, aber die Prototypmethode wird über die Prototypkette gefunden Fn.prototype = this.prototype fBind.prototype = neue Fn() Rückgabewert fBind } Für die oben beschriebene Situation können Sie mithilfe einer Funktions-Middleware die Prototypenkette nutzen, um die ursprüngliche Methode oder Eigenschaft des Funktionsprototyps zu finden. Anruf Der Unterschied zwischen „call“ und „apply“ besteht lediglich in den unterschiedlichen Verarbeitungsparametern. Alles andere ist ähnlich. Function.prototype.mybind = Funktion (Kontext, ...args1) { lass das = dies Funktion fBind(...args2) { gib das zurück.Aufruf(diese Instanz von fBind? dies: Kontext, …Argumente1, …Argumente2) } Funktion Fn() { } Fn.prototype = dieser.prototype fBind.prototype = neue Fn() Rückgabewert fBind } ZusammenfassenDamit ist dieser Artikel über die Implementierungsprinzipien von call, apply und bind in JavaScript abgeschlossen. Weitere Informationen zu den Prinzipien von call, apply und bind finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
>>: Lösungen für MySQL-Batch-Insert- und eindeutige Indexprobleme
Derzeit habe ich ein Projekt erstellt, die Schnitt...
Inhaltsverzeichnis 1. E-Mail 2. Mobiltelefonnumme...
Beispiel-Quellcode: https://codepen.io/shadeed/pe...
Der einfache Timer von Vue dient Ihnen als Refere...
Inhaltsverzeichnis Vorwort Zweidimensionales Arra...
beschreiben: Installieren Sie die VM unter Window...
<br />Dieses Tag kann eine horizontale Linie...
Dieser Artikel stellt hauptsächlich vor, wie man ...
JavaScript-Skripte können überall in HTML eingebe...
Inhaltsverzeichnis Hintergrund Welche Methoden gi...
Inhaltsverzeichnis Kanal Maxwell Datenbus Datenüb...
1. Verwendung des CSS-Bereichs (Stilaufteilung) I...
1. Herunterladen und installieren Laden Sie die D...
Wir alle kennen die Drag-and-Drop-Funktion von HT...
MQTT-Protokoll MQTT (Message Queuing Telemetry Tr...