2010-11-12 12 views
5

Je suis un débutant dans js, et je suis intrigué par le code suivant:javascript prototype et « ce » l'accès à la fermeture

Foo = function(arg) { 
    this.arg = arg; 
}; 

Foo.prototype = { 
    init: function() { 
     var f = function() { 
      alert("current arg: " + this.arg); // am expecting "bar", got undefined 
     } 
     f(); 
    } 
}; 

var yo = Foo("bar"); 
yo.init(); 

je devais obtenir « arg actuelle: bar », mais j'ai reçu « courant arg: indéfini ". J'ai remarqué que en copiant this.arg dans une « normale » première variable, et cette variable dans se référant à la fermeture fonctionne:

Foo.prototype = { 
    init: function() { 
     var yo = this.arg; 
     var f = function() { 
      alert("current arg: " + yo);   } 
     f(); 
    } 
}; 

que je fais quelque chose de mal, a obtenu de mauvaises attentes, ou bien elle tombe dans l'une des js WTF?

+0

Copier 'this.arg' dans une variable" normale "ne fera rien d'autre que ce que' this' signifie pour votre fonction. – bobobobo

+0

@bobobobo Techniquement vrai, mais quand est-ce que quelqu'un a laissé entendre que cela arriverait? La façon dont vous avez formulé cela pourrait être trompeuse. Il n'utilisait en fait pas ceci dans le deuxième exemple; l'utilisation de la variable locale 'yo' crée une fermeture qui garde la référence à l'objet prévu même à l'intérieur de la fonction' f'. – theazureshadow

Répondre

3

Cela dépend de la façon dont la fonction a été invoquée.

Si invoqué avec le mot-clé new alors this fait référence à l'objet en cours de construction (qui sera implicitement retourné à la fin de la fonction).

Si invoqué en tant que fonction normale, this fait référence à l'objet global window.

Exemple:

// Constructor for Foo, 
// (invoke with keyword new!) 
function Foo() 
{ 
    this.name = "Foo" ; 
} 

myFoo = new Foo() ; 
alert('myFoo ' + myFoo.name + '\n' + 'window: ' + window.name) ; // window.name will be empty 

// now if we invoke Foo() WITHOUT keyword NEW 
// then all references to `this` inside the 
// function Foo will be to the 
// __global window object__, i.e. the global window 
// object will get clobbered with new properties it shouldn't 
// have! (.name!) 

Foo() ; // incorrect invokation style! 
alert('myFoo ' + myFoo.name + '\n' + 'window: ' + window.name) ; 

JavaScript ne pas « constructeurs » en soi, la seule JavaScript façon sait que votre function est en fait un « constructeur » est de style invokation (à savoir vous en utilisant le mot new chaque fois que vous invoquez it)

4

Les fonctions de vanille seront exécutées avec this en se référant à window. Votre deuxième morceau de code est un exemple parfait de la façon de contourner ce problème en utilisant des fermetures.

(Vous pouvez également utiliser call et apply pour appeler une fonction à un contexte particulier.)

+0

Ah, cela explique le comportement. Merci ! –

+0

C'est dommage que les downvotes soient anonymes. Pour quiconque downvoted, j'apprécierais un commentaire :) – theazureshadow