2009-02-06 7 views
71

J'ai créé un 'contrôle' en utilisant jQuery et ai utilisé jQuery.extend pour aider à le rendre aussi OO possible.Contrôle de la valeur de 'this' dans un événement jQuery

Au cours de l'initialisation de mon contrôle câbler en divers événements de clic comme si

jQuery('#available input', 
      this.controlDiv).bind('click', this, this.availableCategoryClick); 

Notez que je suis PASING « ceci » comme argument de données dans la méthode de liaison. Je fais ceci afin que je puisse obtenir des données attachées à l'instance de contrôle plutôt qu'à partir de l'élément qui déclenche l'événement click.

Cela fonctionne parfaitement, mais je pense qu'il ya une meilleure façon

Après avoir utilisé Prototype dans le passé, je me souviens d'une syntaxe de liaison qui vous a permis de contrôler ce que la valeur de « ce » était à l'événement.

Quelle est la méthode jQuery?

+0

J'sais pourquoi vous essayez de faire jQuery OO depuis jQuery est plus fonctionnel que OO. – cletus

Répondre

98

Vous pouvez utiliser jQuery.proxy() avec fonction anonyme, juste un peu maladroite que « contexte » est le second paramètre.

$("#button").click($.proxy(function() { 
    //use original 'this' 
},this)); 
20

Je ne pense pas que jQuery a une fonctionnalité intégrée pour cela. Mais vous pouvez utiliser une aide à construire comme ce qui suit:

Function.prototype.createDelegate = function(scope) { 
    var fn = this; 
    return function() { 
     // Forward to the original function using 'scope' as 'this'. 
     return fn.apply(scope, arguments); 
    } 
} 

// Then: 
$(...).bind(..., obj.method.createDelegate(obj)); 

De cette façon, vous pouvez créer des « fonctions wrapper » dynamiques avec createDelegate() qui appellent la méthode avec un objet donné que son champ d'application « ceci ».

Exemple:

function foo() { 
    alert(this); 
} 

var myfoo = foo.createDelegate("foobar"); 
myfoo(); // calls foo() with this = "foobar" 
+39

Les gars, cet article a été écrit en février 2009, il n'y avait pas encore de 'jQuery.proxy()' (apparu dans v.1.4, janvier 2010). Pas besoin de downvote. –

+5

N'est-il pas question de donner les meilleures réponses au plus grand nombre de votes? J'apprécie que les réponses dépassées soient rejetées ou votées. Il permet d'éviter l'erreur IMHO. – ben

+1

Bien sûr, la meilleure réponse devrait obtenir le plus de votes, comme c'est le cas ici. Mais cela ne signifie pas que les meilleures réponses devraient être rejetées. Cela diminue la réputation et n'est tout simplement pas juste. Qu'attendez-vous que je fasse? Vérifier et réviser mes anciennes réponses sur une base régulière? –

2

jQuery ne supporte pas les lie et le moyen préféré consiste à utiliser des fonctions.

Parce que Javascript, this.availableCategoryClick ne signifie pas appeler la fonction availableCategoryClick sur cet objet jQuery conseille d'utiliser cette syntaxe préférée:

var self = this; 
jQuery('#available input', self.controlDiv).bind('click', function(event) 
{ 
    self.availableCategoryClick(event); 
}); 

concepts OO en Javascript sont difficiles à comprendre, est souvent la programmation fonctionnelle plus facile et plus lisible.

1

Voyant que les fonctions modifient la portée, la manière la plus courante consiste à le faire à la main, avec quelque chose comme var self = this.

var self = this 

$('.some_selector').each(function(){ 
    // refer to 'self' here 
} 
+0

convention dit que vous devriez utiliser 'that' à la place .. – Orlando

36

J'aime votre chemin, en fait utiliser une construction similaire:

$('#available_input').bind('click', {self:this}, this.onClick); 

et la première ligne de this.onClick:

var self = event.data.self; 

J'aime cette façon parce que vous obtenez à la fois l'élément a cliqué (comme ceci) et l'objet "this" en tant que tel sans avoir à utiliser de fermetures.

+0

c'est en fait très utile, la meilleure approche que j'ai vu jusqu'ici .. merci mec! –

+0

Solution pure. J'aime ça. –

+0

Bonne idée, merci! –

32

jQuery a la méthode jQuery.proxy (disponible depuis la version 1.4).

Exemple:

var Foo = { 
    name: "foo", 

    test: function() { 
    alert(this.name) 
    } 
} 

$("#test").click($.proxy(Foo.test, Foo)) 
// "foo" alerted 
4

vous pouvez utiliser la méthode bind javascript comme ceci:

var coolFunction = function(){ 
    // here whatever involving this 
    alert(this.coolValue); 
} 

var object = {coolValue: "bla"}; 


$("#bla").bind('click', coolFunction.bind(object)); 
+0

Hélas, cela semble être seulement dans JS 1.8.5, et cela supprime les navigateurs tels que IE8. –

+1

@LukeH méthode de liaison est juste un code js .. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – Orlando

+1

@JLRishe vous pouvez utiliser ce [polyfill] (https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility) pour IE8 – Orlando

4

HTML navigateurs 5 conformes fournissent une bind method sur Function.prototype qui est probablement la plus propre syntaxe et ne dépend pas de cadre, bien qu'il est pas intégrée dans IE jusqu'à IE 9. (il y a un polyfill pour les navigateurs sans, cependant.)

sur la base de votre exemple, vous pouvez l'utiliser comme ceci:

jQuery('#available input', 
     this.controlDiv).bind('click', this.availableCategoryClick.bind(this)); 

(remarque: la première bind dans cette déclaration fait partie de jQuery et n'a rien à voir avec Function.prototype.bind)

Ou utiliser un peu plus concis et à jour jQuery (et éliminer toute confusion de deux types différents de bind s):

$('#available input', this.controlDiv).click(this.availableCategoryClick.bind(this)); 
Questions connexes