Maison  >  Article  >  interface Web  >  Explication détaillée des fonctions de liaison de fonctions et de liaison d'événements de classe en JavaScript dans ES6

Explication détaillée des fonctions de liaison de fonctions et de liaison d'événements de classe en JavaScript dans ES6

小云云
小云云original
2017-12-23 10:29:441936parcourir

Cet article présente principalement l'implémentation JavaScript des fonctions de liaison de fonctions et de liaison d'événements de classe dans ES6, et analyse les principes, les méthodes d'implémentation, les techniques d'exploitation associées et les précautions de liaison de fonctions et de liaison d'événements de classe dans ES6 sous forme d'exemples. ceux qui en ont besoin peuvent s'y référer, j'espère que cela pourra aider tout le monde.

Liaison de fonction

Les fonctions fléchées peuvent lier cet objet, ce qui réduit considérablement le nombre de façons de lier explicitement cet objet (appeler, appliquer, lier). Cependant, les fonctions fléchées ne conviennent pas à toutes les situations, c'est pourquoi ES7 propose l'opérateur « function bind » pour remplacer les appels call, apply et bind. Bien que cette syntaxe soit encore une proposition ES7, le transcodeur Babel la prend déjà en charge.

L'opérateur de liaison de fonction est constitué de deux doubles deux-points ( :: ) côte à côte. Le côté gauche du double deux-points est un objet et le côté droit est une fonction. Cet opérateur liera automatiquement l'objet de gauche comme contexte (c'est-à-dire cet objet) à la fonction de droite.

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);
}

Si le côté gauche du double deux-points est vide et que le côté droit est une méthode d'un objet, cela équivaut à lier la méthode à l'objet.

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

Étant donné que l'opérateur double deux-points renvoie toujours l'objet d'origine, l'écriture en chaîne peut être utilisée.

// 例一
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");

Liaison d'événements dans les classes

Présentation

ES6 fournit des classes, ce qui apporte une grande aide à la modularisation. Lier des événements dans une classe vise, d'une part, à rendre la structure du code claire, et d'autre part, à permettre l'utilisation des variables et des méthodes de la classe. Cependant, comme la fonction de rappel d'événement n'est pas déclenchée par l'objet instance de la classe, la variable this de la classe n'est pas accessible dans la fonction de rappel d'événement. De plus, nous ne voulons pas que la fonction de rappel d'événement soit exposée au monde extérieur afin que l'appelant ne puisse pas l'appeler directement.

Pour faire simple, nous espérons :

1. La fonction de rappel d'événement doit pouvoir accéder à la variable this de la classe
2. La fonction de rappel d'événement ne peut pas être appelée directement.

Que diriez-vous d'accéder au this de la classe

Solution 1 : Enregistrer le this de la classe en tant que variable locale

La référence de this change dynamiquement, mais la référence de la variable locale est claire et les variables locales définies par une fonction sont disponibles dans toute la fonction. Nous pouvons donc utiliser let that = this pour enregistrer la variable this de la classe.

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();
  }
}

Cette méthode n'est utile que lors de l'utilisation de jquery, car les événements de dissociation jquery n'ont pas besoin de fournir une fonction de rappel, juste à côté. Mais il y a une raison pour laquelle js natif doit fournir des fonctions de rappel, car le même événement du même élément peut être lié à plusieurs fonctions de rappel, vous devez donc indiquer laquelle libérer.

Option 2 : utilisez bind() pour changer le point de ceci

Il y a la classe A. Dans A, vous devez ajouter l'événement mousemove Écrivez le code suivant selon les exigences :

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

Cependant, cela ne peut pas être obtenu auprès de la classe. Celui de onMouseMove pointera vers le document. Étant donné que l'événement est ajouté au document, l'événement est naturellement déclenché par le document et onMouseMove est appelé pour le traitement, donc ceci dans onMouseMove pointe vers le document.

L'approche la plus correcte est : utilisez la fonction bind() pour changer le pointeur de this dans onMouseMove, et en même temps déplacez la fonction de rappel d'événement en dehors de la classe :

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

Mais il y a encore des problèmes, l'événement ne peut pas être supprimé ! Parce que this.bind() renvoie une nouvelle fonction à chaque fois qu'elle est appelée, les seconds paramètres de

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

et

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

ne sont pas les mêmes.

L'approche correcte est : Enregistrez le résultat de bind() dans une variable :

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);
}

Comment définir une fonction de rappel d'événement privé

En Java, ne Je ne veux pas Les méthodes exposées au monde extérieur peuvent être définies comme des méthodes privées, mais ES6 ne fournit pas de méthodes privées et ne peut être simulé que par certaines méthodes. Cependant, la fonction de rappel d'événement est particulière car l'événement doit être supprimé en plus d'être défini, ce qui entraînera des problèmes supplémentaires. Mais il existe encore un moyen :

Utilisez la variable Symbol pour définir

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") produira une valeur unique, qui est générée lors de la création de l'objet, donc l'appelant n'a aucun moyen de connaître cette valeur lors de l'écriture du code, donc la méthode nommée en utilisant cette valeur ne peut pas être appelée, définissant ainsi une méthode privée.

Recommandations associées :

Explication de l'utilisation de la liaison de fonction JavaScript avec des exemples

Explication détaillée de la façon d'utiliser le code de liaison de fonction pour l'interaction JavaScript

Liaison de fonction JavaScript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn