Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung der Funktionsbindungs- und Klassenereignisbindungsfunktionen in JavaScript in ES6

Detaillierte Erläuterung der Funktionsbindungs- und Klassenereignisbindungsfunktionen in JavaScript in ES6

小云云
小云云Original
2017-12-23 10:29:441920Durchsuche

In diesem Artikel wird hauptsächlich die JavaScript-Implementierung von Funktionsbindungs- und Klassenereignisbindungsfunktionen in ES6 vorgestellt und anhand von Beispielen die Prinzipien, Implementierungsmethoden, zugehörigen Betriebstechniken und Vorsichtsmaßnahmen für die Funktionsbindung und Klassenereignisbindung in ES6 analysiert In Not kann man sich darauf beziehen, ich hoffe, es kann allen helfen.

Funktionsbindung

Pfeilfunktionen können dieses Objekt binden, wodurch die Anzahl der Möglichkeiten zur expliziten Bindung dieses Objekts (Aufrufen, Anwenden, Binden) erheblich reduziert wird. Da Pfeilfunktionen jedoch nicht für alle Situationen geeignet sind, schlägt ES7 den Operator „Funktionsbindung“ vor, um Aufruf-, Anwendungs- und Bindungsaufrufe zu ersetzen. Obwohl es sich bei dieser Syntax noch um einen ES7-Vorschlag handelt, wird sie vom Babel-Transcoder bereits unterstützt.

Der Funktionsbindungsoperator besteht aus zwei nebeneinander liegenden Doppelpunkten ( :: ). Die linke Seite des Doppelpunkts ist ein Objekt und die rechte Seite ist eine Funktion. Dieser Operator bindet automatisch das Objekt auf der linken Seite als Kontext (d. h. dieses Objekt) an die Funktion auf der rechten Seite.

foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
return obj::hasOwnProperty(key);
}

Wenn die linke Seite des Doppelpunkts leer ist und die rechte Seite eine Methode eines Objekts ist, entspricht dies der Bindung der Methode an das Objekt.

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;
let log = ::console.log;
// 等同于
var log = console.log.bind(console);

Da der Doppelpunktoperator immer noch das ursprüngliche Objekt zurückgibt, kann Kettenschreiben verwendet werden.

// 例一
import { map, takeWhile, forEach } from "iterlib";
getPlayers()
::map(x => x.character())
::takeWhile(x => x.strength > 100)
::forEach(x => console.log(x));
// 例二
let { find, html } = jake;
document.querySelectorAll("p.myClass")
::find("p")
::html("hahaha");

Ereignisbindung in Klassen

Übersicht

ES6 bietet Klassen, was eine große Hilfe bei der Modularisierung darstellt. Das Binden von Ereignissen in einer Klasse dient erstens dazu, die Codestruktur klar zu machen und zweitens, damit die Variablen und Methoden der Klasse verwendet werden können. Da die Ereignisrückruffunktion jedoch nicht durch das Instanzobjekt der Klasse ausgelöst wird, kann in der Ereignisrückruffunktion nicht auf diese Variable der Klasse zugegriffen werden. Darüber hinaus möchten wir nicht, dass die Ereignisrückruffunktion der Außenwelt ausgesetzt wird, sodass der Anrufer sie nicht direkt aufrufen kann.

Um es einfach auszudrücken:

1. Die Event-Callback-Funktion muss auf diese Variable der Klasse zugreifen können
2. Die Event-Callback-Funktion kann nicht direkt aufgerufen werden

Wie wäre es mit dem Zugriff auf das This der Klasse

Lösung 1: Speichern Sie das This der Klasse als lokale Variable

Die Referenz von this ändert sich dynamisch, aber die Referenz von Die lokale Variable ist klar und die von einer Funktion definierten lokalen Variablen sind in der gesamten Funktion verfügbar. Wir können also let that = this verwenden, um die Variable this der Klasse zu speichern.

class A{
  //绑定事件的方法
  bindEvent(){
   let that = this;
   this.button1.on('click',function(e){
      this.addClass('on'); //this指代所点的元素
      that.doSomething(); //that指向类的this
   })
  }
  doSomething(){
   //事件处理函数
  }
  //解绑事件
  unBindEvent(){
   this.button1.off();
  }
}

Diese Methode ist nur bei Verwendung von Jquery nützlich, da JQuery-Entbindungsereignisse keine Rückruffunktion bereitstellen müssen, sondern einfach ausgeschaltet sind. Es gibt jedoch einen Grund, warum natives JS Rückruffunktionen bereitstellen muss, da dasselbe Ereignis desselben Elements an mehrere Rückruffunktionen gebunden sein kann und Sie daher angeben müssen, welche freigegeben werden soll.

Option 2: Verwenden Sie bind(), um den Punkt davon zu ändern

Es gibt Klasse A. In A müssen Sie den folgenden Code entsprechend den Anforderungen hinzufügen:

class A{
  //添加事件
  addEvent(){
    document.addEventListener( 'mousemove', onMouseMove, false );
  }
  //添加事件
  removeEvent(){
    document.removeEventListener( 'mousemove', onMouseMove , false );
  }
}
//事件回调函数中
function onMouseMove(event){
  console.log(this);  //#document
}

Diese kann jedoch nicht aus der Klasse bezogen werden. onMouseMove zeigt auf das Dokument. Da das Ereignis dem Dokument hinzugefügt wird, wird das Ereignis natürlich durch das Dokument ausgelöst und onMouseMove zur Verarbeitung aufgerufen, sodass dies in onMouseMove auf das Dokument verweist.

Der korrektere Ansatz ist: Verwenden Sie die Funktion bind(), um den Zeiger davon in onMouseMove zu ändern, und verschieben Sie gleichzeitig die Ereignisrückruffunktion aus der Klasse:

class A{
  //添加事件
  addEvent(){
    document.addEventListener( 'mousemove', onMouseMove.bind(this), false );
  }
  //添加事件
  removeEvent(){
    document.removeEventListener( 'mousemove', onMouseMove.bind(this) , false );
  }
}
//事件回调函数中
function onMouseMove(event){
  console.log(this);
}

Aber es gibt immer noch Probleme, das Ereignis kann nicht entfernt werden! Da this.bind() bei jedem Aufruf eine neue Funktion zurückgibt, sind die zweiten Parameter von

document.addEventListener( 'mousemove', onMouseMove.bind(this), false );

und

document.removeEventListener( 'mousemove', onMouseMove.bind(this), false );

nicht identisch.

Der richtige Ansatz ist: Speichern Sie das Ergebnis von bind() in einer Variablen:

class A{
  constructor(){
    this._onMouseMove = onMouseMove.bind(this);  //看这里
  }
  //添加事件
  addEvent(){
    document.addEventListener( 'mousemove', this._onMouseMove , false );
  }
  //添加事件
  removeEvent(){
    document.removeEventListener( 'mousemove', this._onMouseMove , false );
  }
}
//事件回调函数中
function onMouseMove(event){
  console.log(this);
}

So definieren Sie eine Rückruffunktion für private Ereignisse

In Java nicht Ich möchte nicht, dass Methoden, die der Außenwelt ausgesetzt sind, als private Methoden definiert werden können. ES6 bietet jedoch keine privaten Methoden und kann nur durch einige Methoden simuliert werden. Die Ereignisrückruffunktion ist jedoch etwas Besonderes, da das Ereignis nicht nur definiert, sondern auch entfernt werden muss, was zusätzliche Probleme verursacht. Aber es gibt immer noch eine Möglichkeit:

Verwenden Sie die Variable Symbol, um

const _onMouseMove = Symbol("_onMouseMove");
class A{
  constructor(){
    this[_onMouseMove] = onMouseMove.bind(this);
  }
  //添加事件
  addEvent(){
    document.addEventListener( 'mousemove', this[_onMouseMove] , false );
  }
  //添加事件
  removeEvent(){
    document.removeEventListener( 'mousemove', this[_onMouseMove] , false );
  }
}
//事件回调函数中
function onMouseMove(event){
  console.log(this);
}

Symbol("_onMouseMove") zu definieren, um einen eindeutigen Wert zu erzeugen, der generiert wird, wenn das Objekt erstellt wird Der Aufrufer hat beim Schreiben von Code keine Möglichkeit, diesen Wert zu kennen, daher kann die mit diesem Wert benannte Methode nicht aufgerufen werden, wodurch eine private Methode definiert wird.

Verwandte Empfehlungen:

Erklärung der Verwendung von JavaScript-Funktionsbindungen anhand von Beispielen

Detaillierte Erläuterung der Verwendung von Funktionsbindungscode für die JavaScript-Interaktion

JavaScript-Funktionsbindung

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Funktionsbindungs- und Klassenereignisbindungsfunktionen in JavaScript in ES6. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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