2010-04-13 5 views
4

Ceci est un très vieux problème, mais je n'arrive pas à comprendre les autres solutions présentées ici.Javascript: Accéder à la bonne portée "sous" appliquer (...)

J'ai un objet

function ObjA() { 
    var a = 1; 
    this.methodA = function() { 
     alert(a); 
    } 
} 

qui est instancié comme

var myObjA = new ObjA(); 

Plus tard, je céder mes methodA en fonction de gestionnaire dans un cadre Javascript externe, qui invoque à l'aide de la méthode apply(...) . Lorsque la structure externe exécute mon methodA, this appartient à la fonction de cadre qui appelle ma méthode.

Puisque je ne peux pas changer comment ma méthode est appelée, comment puis-je retrouver l'accès à la variable privée a? Mes recherches indiquent que les fermetures pourraient être ce que je cherche.

Répondre

2

Vous avez déjà une fermeture. Lorsque methodA est appelé l'accès à a fonctionnera bien.

Les propriétés des objets sont différentes des objets. Vous utilisez des étendues pour implémenter quelque chose qui se comporte bit comme 'membres privés' dans d'autres langues, mais a est une variable locale dans la portée parente, et pas un membre de myObjA (privé ou autre). Avoir une fonction comme methodA conserver l'accès aux variables dans sa portée parent est ce que signifie une «fermeture».

Les étendues auxquelles vous pouvez accéder sont réparées: vous pouvez toujours accéder aux variables de vos portées parentes, quelle que soit la manière dont vous êtes rappelé, et vous ne pouvez pas appeler une fonction avec des portées différentes de celles qu'elle avait lorsqu'elle était définie.

Étant donné que a n'est pas une propriété de this, il n'est pas important que this ne soit pas conservé lorsque vous rappelez.Si vous ne besoin d'obtenir le this correct alors oui, vous aurez besoin de plus de travail, soit en utilisant une autre fermeture sur myObjA lui-même:

onclick= function() { myObjA.methodA(); }; 

ou en utilisant Function#bind:

onclick= myObjA.methodA.bind(myObjA); 
+0

Vous avez raison. J'ai vraiment accès à 'a', mais je ne peux pas le vérifier en utilisant Firebug. Mais merci beaucoup de m'avoir éclairé! – Chau

+0

Vous pouvez voir les portées parents et leurs variables dans Firebug en regardant à l'intérieur de la pseudo-variable 'scopeChain' dans l'onglet 'Watch'. – bobince

+0

Oui oui, je sais. Mais ces variables n'apparaissent pas dans mon firebug. Je ne peux pas non plus y accéder dans la console - bien que ça ne réponde pas comme si elles n'étaient pas définies, juste aucune réponse. – Chau

1

oui, vous avez raison. Au lieu d'une référence de méthode

var myObjA = new ObjA(); 

libraryCallback = myObjA.methodA 

passer une fermeture

libraryCallback = function() { myObjA.methodA() } 
0

Si vous êtes en utilisant jQuery framework javascript, moyen le plus simple est d'utiliser proxy:

$('a').click($.proxy(myObjA, 'methodA')); 
+0

Je n'utilise pas jQuery. – Chau

0

Je ferais ceci:

function ObjA() { 
    this.a = 1; 
    this.methodA = function() { 
     alert(this.a); 
    } 
} 

function bindMethod(f, o) { 
    return function(){ 
     return f.apply(o, arguments); 
    } 
} 

var myObjA = new ObjA(); 
myObjA.methodA = bindMethod(myObjA.methodA, myObjA); 
... 

bindMethod lie la méthode methodA pour être toujours une méthode de myObjA en passant encore sur les arguments qui function() {myObjA.methodA()} ne fait pas.