Pour une raison quelconque, j'obtiens des valeurs étranges pour "ceci" dans ma classe es6 ...
'use strict';
class Clicker {
constructor(element) {
this.count = 0;
this.elem = element;
this.elem.addEventListener('click', this.click);
// logs Clicker { count:0, elem: button#thing} as expected
console.log(this);
}
click() {
// logs <button id="thing">...</button> as unexpected...
console.log(this);
this.count++;
}
}
var thing = document.getElementById('thing');
var instance = new Clicker(thing);
<button id="thing">Click me</button>
Pourquoi le "ceci" à l'intérieur de la méthode click des Clickers fait-il référence au nœud dom plutôt qu'à ... lui-même?
Plus important encore, comment puis-je faire référence à la propriété count Clickers à partir de sa méthode click si je ne peux pas utiliser "this" pour le faire?
Pourquoi le "ceci" à l'intérieur de la méthode click des Clickers fait-il référence au nœud dom plutôt qu'à ... lui-même?
Parce que la spécification de .addEventListener()
est de définir le pointeur this
sur l'élément DOM qui a intercepté l'événement. Voilà comment il est conçu pour fonctionner.
Lorsque vous passez une méthode en tant que rappel où vous souhaitez remplacer la valeur de this
, vous pouvez utiliser .bind()
pour forcer la valeur souhaitée de this
avec:
this.elem.addEventListener('click', this.click.bind(this));
Explication:
Tous les appels de fonction en Javascript définissent une nouvelle valeur de this
selon la façon dont la fonction est appelée. Voir cette explication pour plus d'informations sur cet ensemble de règles de base.
En plus de cela, lorsque vous faites cela:
this.elem.addEventListener('click', this.click);
Vous obtenez simplement la méthode this.click
Et passez cette méthode seule à addEventListener()
. La valeur de this
sera complètement perdue. C'est comme si vous faisiez cela:
var m = this.click; // m here is just a reference to Clicker.prototype.click
this.elem.addEventListener('click', m);
En plus de cela, .addEventListener()
est spécialement conçu pour définir sa propre valeur de this
lorsqu'il appelle le rappel (pour pointer this
sur l'élément créant l'événement).
Ainsi, vous pouvez utiliser .bind()
comme indiqué ci-dessus pour forcer la valeur appropriée de this
à être en place lorsque votre méthode est appelée.
Pour référence, vous pouvez trouver cette description des six façons dont this
est défini pour qu'un appel de fonction en Javascript soit utile.
Autres options
Je trouve que .bind()
est le moyen le plus clair de le définir, mais vous pouvez également utiliser une fonction anonyme locale:
var self = this;
this.elem.addEventListener('click', function() {
self.click();
});
ou dans ES6, une fonction flèche:
this.elem.addEventListener('click', () => this.click());
La fonction flèche conservera automatiquement la valeur de this
pour éviter d'avoir besoin de la référence self
utilisée dans l'exemple précédent.