Detaillierte Erläuterung der Implementierungsprinzipien von call, apply und bind in JavaScript

Detaillierte Erläuterung der Implementierungsprinzipien von call, apply und bind in JavaScript

Vorwort

Wie 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.

Anruf

Die 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.

Verwendung

Funktion Spaß() {
  console.log(dieser.Name, Argumente)
}
let obj = { name: 'clying' }
Spaß.call(Objekt, 'deng', 'deng')
// klicken [Argumente] { '0': 'deng', '1': 'deng' }

erreichen

Die 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.

Verwendung

Legen 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]

erreichen

Implementieren 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
}

binden

Die 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.

Verwendung

Binden 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
}

Zusammenfassen

Damit 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:
  • Beispielcode für die Verwendung von JS zur einfachen Implementierung der Methoden „Apply“, „Call“ und „Bind“
  • So implementieren Sie Call, Apply und Binding in nativem JS
  • So implementieren Sie eine einfache Version von Call, Apply, Binding mit 50 Zeilen Javascript-Code
  • Detaillierte Erklärung des Codes zur Implementierung von call, bind und apply in Javascript

<<:  Praktische Erfahrung mit der Implementierung von Nginx zum Weiterleiten von Anfragen basierend auf URLs

>>:  Lösungen für MySQL-Batch-Insert- und eindeutige Indexprobleme

Artikel empfehlen

Lösung zur Schnittstellenverformung beim Einstellen der Frameset-Höhe

Derzeit habe ich ein Projekt erstellt, die Schnitt...

Häufig verwendete JS-Funktionsmethoden im Frontend

Inhaltsverzeichnis 1. E-Mail 2. Mobiltelefonnumme...

So verbergen Sie Elemente im Web und ihre Vor- und Nachteile

Beispiel-Quellcode: https://codepen.io/shadeed/pe...

Implementierung eines einfachen Timers basierend auf der Vue-Methode

Der einfache Timer von Vue dient Ihnen als Refere...

Lösen Sie das Problem des Docker-Pull-Image-Fehlers

beschreiben: Installieren Sie die VM unter Window...

HTML-Tutorial: Horizontales Liniensegment in HTML

<br />Dieses Tag kann eine horizontale Linie...

Detaillierte Erklärung, wann Javascript-Skripte ausgeführt werden

JavaScript-Skripte können überall in HTML eingebe...

Zusammenfassung verschiedener Methoden zur JS-Datentyperkennung

Inhaltsverzeichnis Hintergrund Welche Methoden gi...

Vergleichende Analyse von MySQL Binlog-Protokollverarbeitungstools

Inhaltsverzeichnis Kanal Maxwell Datenbus Datenüb...

Zusammenfassung der Verwendung des CSS-Bereichs (Stilaufteilung)

1. Verwendung des CSS-Bereichs (Stilaufteilung) I...

Detaillierte Installation und Konfiguration von MySql auf dem Mac

1. Herunterladen und installieren Laden Sie die D...

So erstellen Sie ein Drag & Drop-Plugin mit benutzerdefinierten Vue-Direktiven

Wir alle kennen die Drag-and-Drop-Funktion von HT...