C'est en fait assez simple une fois que vous avez compris comment les méthodes fonctionnent en javascript dans les coulisses.
toUpperCase
est une méthode. Il s'agit d'une fonction qui opère sur un objet spécifique... généralement via la fonction this
variable.
Javascript est un langage prototypique... ce qui signifie que les fonctions attachées aux objets sont juste des fonctions et peuvent être copiées. Il y a un travail en coulisse qui permet de s'assurer que this
est réglé sur la bonne chose lorsque vous appelez une méthode, mais ce travail ne se produit que lorsque vous l'appelez en tant que méthode... comme dans l'exemple suivant obj.method()
formulaire.
En d'autres termes : ''.toUpperCase()
s'assure que this
est défini comme la chaîne de caractères ''
quand vous l'appelez.
Quand vous l'appelez comme toUpperCase()
this
n'a pas de valeur particulière (des environnements différents font des choses différentes avec l'option this
dans ce cas)
Ce que fait votre code pourrait être réécrit comme ceci :
var function_to_call;
if (true) {
function_to_call = ''.toLowerCase;
} else {
function_to_call = ''.toUpperCase;
}
function_to_call();
Parce que votre appel de fonction : function_to_call()
n'est pas dans le object.method()
la syntaxe, la chose qui met this
à l'objet correct n'est pas fait, et votre appel de fonction s'exécute avec this
n'est pas réglé sur ce que vous voulez.
Comme d'autres personnes l'ont souligné, vous pouvez utiliser func.call(thing_to_make_this)
o func.apply()
pour attacher la chose correcte à ceci explicitement.
Je trouve beaucoup plus utile d'utiliser .bind()
- qui est extrêmement sous-utilisé à mon avis. function_name.bind(this_object)
vous donne une nouvelle fonction qui aura toujours this
attaché à la bonne chose :
// assuming function_to_call is set
function_that_works = function_to_call.bind(my_object)
function_that_works(); // equivalent to my_object.function_to_call()
et cela signifie que vous pouvez faire circuler la fonction que vous obtenez de la part de bind()
comme vous le feriez pour une fonction normale, et elle fonctionnera sur l'objet que vous voulez. Ceci est particulièrement utile dans les callbacks, car vous pouvez créer une fonction anonyme qui est liée à l'objet dans lequel elle a été créée :
// this won't work because when this runs, 'this' doesn't mean what you think
setTimeout(function() { this.display_message('success'); }, 2000);
// this will work, because we have given setTimeout a pre-bound function.
setTimeout(function() { this.display_message('success'); }.bind(this), 2000);
TL;DR : Vous ne pouvez pas appeler une méthode en tant que fonction et vous attendre à ce que cela fonctionne, parce qu'elle ne sait pas ce qu'elle doit faire. this
devrait être. Si vous voulez utiliser cette fonction, vous devez utiliser .call()
, .apply()
o .bind()
pour s'assurer this
est correctement défini au moment de l'exécution de la fonction.
J'espère que cela vous aidera.
2 votes
Quand vous le faites
dog.bark()
,this
à l'intérieur debark
pointera versdog
. Mais quand vous le faitesfn = dog.bark
vous copiez la référence de la fonction. Ainsi, dansfn()
,this
pointera verswindow
oundefined
en fonction de l'environnement.0 votes
En rapport : stackoverflow.com/questions/13441307/
6 votes
Que voulez-vous dire par "temps de compilation" JavaScript n'est pas un langage compilé. Il n'y a qu'un temps d'exécution.
0 votes
@alexisking Merci, ça fait des lustres que je cherche un duplicata correct. N'avons-nous pas quelque chose de mieux que Comment accéder à la bonne
this
/ contexte dans un callback y Comment fonctionne le mot-clé "this" ? ? Il faut se demander pourquoi les méthodes de JS ne fonctionnent pas déjà comme celles de Python !0 votes
J'ai aussi trouvé Javascript a perdu son contexte lorsqu'il a été assigné à une autre variable , Pourquoi apply n'est-il pas déjà lié aux fonctions en Javascript ? y Nature des fonctions liées à la JS et opérateur d'invocation de fonction .