2009-12-30 8 views
2

Salut J'ai le code JavaScript suivant que j'essaie de lancer. Mon but est de saisir la signification de this dans différentes portées et différents types d'invocations en JavaScript.Confusion avec "cet" objet dans les fonctions anonymes de JavaScript

Si vous regardez dans le code ci-dessous: J'ai une fonction interne anonyme, qui est affectée à la variable innerStuff. Dans cette fonction anonyme en tant que telle this points à window objet et non l'objet fonction externe ou toute autre chose. Événement bien qu'il ait toujours accès aux variables de la fonction out.

De toute façon, je ne suis pas sûr, pourquoi ce serait; mais si vous regardez le code ci-dessous, je passe this sous la forme de that à innerStuff plus tard et cela fonctionne très bien et imprime l'objet avec l'attribut doofus dans la console.

var someStuff = { 
     doofus:"whatever", 
     newF: function() 
     { 
      var that = this; 
      console.log(that); 
      var innerStuff = function(topThis){ 
       console.log(topThis); 
      }; 

      return innerStuff(that); 
     } 
    } 

    someStuff.newF(); 

Maintenant, je ne change que peu de code. Et au lieu d'assigner à innerStuff, je vais juste retourner directement la fonction en invoquant comme indiqué ci-dessous:

var someStuff = { 
     doofus:"whatever", 
     newF: function() 
     { 
      var that = this; 
      console.log(that); 
      return function(that){ 
       console.log(that); 
      }(); 
     } 
    } 

    someStuff.newF(); 

Cette impression indéfinis pour la fonction anonyme interne. Est-ce parce qu'il y a un conflit entre un that qui est passé en paramètre et un that défini en fonction externe? Je pensais que le paramètre aurait outrepassé la visibilité. Pourquoi la valeur ne serait-elle pas conservée?

Ceci est complètement déroutant. Par contre, si je ne réussis pas that, mais que je l'utilise à la place, parce que la visibilité est là, le résultat est correct et comme prévu.

Qu'est-ce qui me manque? Est-ce le conflit entre les variables, présentes dans la même portée? Y at-il une bonne raison, que les fonctions internes ont this lié à l'objet window?

Répondre

9

this dans JavaScript fait référence à l'objet sur lequel vous avez appelé une méthode. Si vous appelez une fonction comme someObject.functionName(args), alors this sera lié à cet objet. Si vous appelez simplement une fonction nue, comme dans functionName(args), alors this sera lié à l'objet window. Dans le deuxième exemple, vous observez la variable that dans votre fonction interne, sans rien y introduire, elle est donc indéfinie.

 var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(); 

Vous voulez probablement les éléments suivants à la place, si vous voulez quelque chose qui est équivalent à votre premier exemple (en passant that dans la fonction intérieure):

 var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(that); 

Ou ce qui suit, si vous n » t veulent l'ombre et il suffit d'utiliser la liaison de la fonction extérieure:

 var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
     }(); 
+0

ah !! Je ne peux pas croire que j'ai raté ça. Merci beaucoup. – Priyank

+0

Eh bien, c'est * complètement * différent de la façon dont les méthodes liées fonctionnent dans tous les autres langages qui les ont ... – bobince

1

Dans votre deuxième exemple, lorsque vous invoquez la fonction anonyme, le paramètre that n'est pas défini (vous ne lui transmettez rien.) Vous pouvez le faire:

newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(that); // note that we are passing our 'that' in as 'that' 
    } 

Cela permet de conserver la valeur correcte de la variable.

Cependant, puisque vous détermination de la portée var that ci-dessus, vous pouvez simplement supprimer le paramètre de la fonction ainsi:

newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
     }(); // 'that' is referenced above. 
    } 

En ce qui pourquoi les fonctions anonymes ont window comme this: chaque fois que vous appelez une fonction sans contexte (ie somef() vs context.somef()) this pointera vers l'objet window.

Vous pouvez remplacer cela et passer un this en utilisant .apply(context, argumentsArray) or .call(context, arg1, arg2, arg3) sur une fonction. Un exemple:

newF: function() 
    { 
     console.log('Outer:', this); 
     var innerF = function(){ 
      console.log('Inner:', this); 
     }; 
     return innerF.apply(this,arguments); 
    } 
1

Dans votre premier exemple de code, la fonction anonyme, bien que déclarée dans une fonction qui est membre de l'objet someStuff, n'est pas membre de l'objet someStuff. Pour cette raison, this dans cette fonction est une référence à l'objet fenêtre. Si vous vouliez appeler la fonction anonyme et avoir le contrôle sur la référence this, vous pouvez effectuer les opérations suivantes:

var someStuff = { 
    doofus:"whatever", 
    newF: function() 
    { 
     var that = this; 
     console.log(that); 
     var innerStuff = function(){ 
      console.log(this); 
     }; 

     return innerStuff.apply(this); 
    } 
} 

someStuff.newF(); 

Dans votre deuxième exemple, votre création en fait une fonction anonyme, l'exécuter, puis retourner la valeur la fonction anonyme est retournée. Cependant, votre fonction anonyme n'a rien retourné. En outre, vous avez un conflit de noms de variables. Vous pourriez faire:

var someStuff = { 
    doofus:"whatever", 
    newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
      return true; 
     }(); 
    } 
} 

someStuff.newF(); 

J'ai ajouté le retour vrai parce que votre fonction doit retourner quelque chose, puisque la fonction qui est en cours d'exécution, il retourne la valeur de retour de la fonction anonyme. Qu'il renvoie vrai ou faux ou une chaîne ou un objet ou autre dépend du scénario.

+0

Je suis d'accord avec le premier point que je pourrais utiliser une invocation "apply", mais le second point est incorrect. Il n'y a pas de conflit de noms car le paramètre passé remplace le param dans la fonction externe. L'erreur que j'ai faite est que je n'ai pas passé le param à la fonction anonyme lors de l'appel. [Comme l'a montré Brian dans l'exemple ci-dessus] Il se tient corrigé que sa solution proposée a très bien fonctionné. Comme pour la valeur de retour; Je ne pense pas que je m'en souciais trop; Je voulais juste voir comment la valeur de ceci/cela était dans la fonction interne. Merci pour votre aide cependant. – Priyank

Questions connexes