jQuery / JavaScript "cette" confusion de pointeur

Le comportement de "this" lorsque la fonction bar est appelée me déconcerte. Voir le code ci-dessous. Existe-t-il un moyen de faire en sorte que "this" soit une ancienne instance d'objet JS lorsque bar est appelée à partir d'un gestionnaire de clics, au lieu d'être l'élément html?

// a class with a method

function foo() {

    this.bar();  // when called here, "this" is the foo instance

    var barf = this.bar;
    barf();   // when called here, "this" is the global object

    // when called from a click, "this" is the html element
    $("#thing").after($("<div>click me</div>").click(barf));
}

foo.prototype.bar = function() {
    alert(this);
}
25
demandé sur I. J. Kennedy 2009-04-02 20:38:33

7 réponses

Bienvenue dans le monde de javascript! : D

Vous avez erré dans le domaine de la portée et de la fermeture javascript.

Pour la réponse courte:

this.bar()

Est exécuté dans le champ d'application de foo, comme ce désigne foo)

var barf = this.bar;
barf();

Est exécuté sous la portée globale.

Ceci.bar signifie essentiellement:

Exécute la fonction pointée par ceci.bar, sous la portée de Ce (foo). Quand tu as copié ça.bar à barf, et exécuter barf. Javascript compris comme, exécutez la fonction pointée par barf, et comme il n'y a pas Ce , Il fonctionne juste dans la portée globale.

Pour corriger cela, vous pouvez modifier

barf();

À quelque chose comme ceci:

barf.apply(this);

Cela indique à Javascript de lier la portée de this à barf avant de l'exécuter.

Pour les événements jquery, vous devrez utiliser une fonction anonyme ou étendre la fonction bind dans prototype pour prendre en charge la portée.

Pour plus info:

35
répondu Aaron Qian 2015-03-13 03:35:10

Il y a une bonne explication sur le mot clé this en JavaScript disponible à QuirksMode .

5
répondu Pawel Krakowiak 2009-04-02 16:58:10
3
répondu Will Dean 2017-05-23 12:10:15

Obtenez le livre: JavaScript: les bonnes parties.

Aussi, lisez autant que vous le pouvez par Douglas Crockford http://www.crockford.com/javascript/

2
répondu Chris Brandsma 2009-04-02 17:10:04

Vous pouvez utiliser Function.apply sur la fonction pour définir ce à quoi this devrait se référer:

$("#thing").after($("<div>click me</div>").click(function() {
    barf.apply(document); // now this refers to the document
});
2
répondu moff 2009-04-02 17:31:33

C'est parce que ce est toujours l'instance que la fonction est attaché. Dans le cas d'un Gestionnaire d'événements c'est la classe qui a déclenché l'événement.

Vous pouvez vous aider avec une fonction anonyme comme celle-ci:

function foo() {
  var obj = this;
  $("#thing").after($("<div>click me</div>").click(function(){obj.bar();}));
}

foo.prototype.bar = function() {
  alert(this);
}
1
répondu Martin 2009-04-02 16:51:25
this.bar();  // when called here, "this" is the foo instance

Ce commentaire est faux lorsque foo est utilisé comme une fonction normale, pas comme un constructeur. ici:

foo();//this stands for window
0
répondu Boki 2014-02-01 03:00:18