Le problème de l'exemple 1 est "ceci" faisant référence au nom global au lieu de l'objet myName.
Je comprends l'utilisation de bind () pour définir la valeur de this sur un objet spécifique. Le problème de l'exemple 1 est donc résolu, mais pourquoi ce problème se produit-il en premier lieu? Est-ce juste la façon dont Javascript a été créé?
Je me demande également pourquoi l'exemple 3 résout le problème et la différence entre les exemples 2 et 3.
this.name = "John"
var myName = {
name: "Tom",
getName: function() {
return this.name
}
}
var storeMyName = myName.getName; // example 1
var storeMyName2 = myName.getName.bind(myName); // example 2
var storeMyName3 = myName.getName(); // example 3
console.log("example 1: " + storeMyName()); // doesn't work
console.log("example 2: " + storeMyName2()); // works
console.log("example 3: " + storeMyName3); // works
Pourquoi JavaScript bind () est-il nécessaire?
La valeur de this
est déterminée par comment une fonction est appelée. Si c'est vous qui appelle la fonction, il n'est généralement pas nécessaire d'utiliser .bind
, car vous avez le contrôle sur la façon d'appeler la fonction, et donc sa valeur this
.
Cependant, c’est souvent pas vous qui appelez la fonction. Les fonctions sont transmises à d'autres fonctions en tant que callbacks et gestionnaires d'événements. Ils sont appelés par le code other et vous n’avez aucun contrôle sur comment la fonction est appelée et vous ne pouvez donc pas contrôler ce que this
désignera.
Si votre fonction nécessite que this
soit définie sur une valeur spécifique et que vous n'êtes pas celui qui appelle la fonction, vous devez .bind
la fonction avec une valeur this
spécifique.
En d'autres termes: .bind
vous permet de définir la valeur de this
sans appeler la fonction now.
Voici une comparaison des fonctions de référence/appelantes:
+-------------------+-------------------+
| | |
| time of | time of |
|function execution | this binding |
| | |
+-------------------+-------------------+-------------------+
| | | |
| function object | future | future |
| f | | |
| | | |
+-------------------+-------------------+-------------------+
| | | |
| function call | now | now |
| f() | | |
| | | |
+-------------------+-------------------+-------------------+
| | | |
| f.call() | now | now |
| f.apply() | | |
| | | |
+-------------------+-------------------+-------------------+
| | | |
| f.bind() | future | now |
| | | |
+-------------------+-------------------+-------------------+
Je me demande également pourquoi l'exemple 3 résout le problème et la différence entre les exemples 2 et 3.
Les exemples 1/2 et 3 ne pourraient pas être plus différents. storeMyName
et storeMyName2
contiennent functions, qui seront appelés ultérieurement, alors que storeMyName3
contient le résultat de l'appel de myName.getName()
à ce moment-là.
Matériel de lecture supplémentaire:
La méthode
bind()
crée une nouvelle fonction qui, lorsqu'elle est appelée, a pour mot clé this la valeur fournie, avec une séquence d'arguments donnée précédant tous ceux fournis lors de l'appel de la nouvelle fonction.
Ainsi, lorsque vous exécutez var storeMyName = myName.getName;
la première fois, il faut la variable globale name
(this.name = "John")
Lorsque vous utilisez la fonction bind()
, elle commence à faire référence au nom défini dans la fermeture actuelle (myName dans ce cas) et imprime donc Tom
Troisième fois, puisque la fonction est appelée immédiatement, son étendue se trouve dans son propre objet local et imprime donc la valeur dans la fermeture Tom
Bind est le mécanisme par lequel vous pouvez changer le contexte d'exécution (ici votre contexte par défaut est global).
Basé sur votre exemple -
var storeMyName = myName.getName;
A partir de la ligne ci-dessus, vous exécutez la fonction storeMyName
dans un contexte global. Ainsi, pour cette exécution, this.name
sera la ligne du haut (c'est-à-dire globale/"John").
var storeMyName2 = myName.getName.bind(myName);
Pour la ligne ci-dessus, vous êtes explicitement changez le contexte d'exécution de la fonction storeMyName2
(en disant que je ne veux pas exécuter cette fonction en tant que fonction globale, je veux exécuter cette fonction dans le contexte de l'objet myName
, donc dans ce cas this.name
sera "Tom")
var storeMyName3 = myName.getName(); // example 3
Et pour cette ligne ci-dessus, vous exécutez juste une fonction sur le contexte d'objet myName
. Plus important encore, vous n'exécutez pas le storeMyName3
et c'est pourquoi son contexte n'est pas global.
Une analogie que j’aime bien, que je n’ai jamais vue nulle part ailleurs: Disons que vous avez un objet foo avec une fonction bar
. Lorsque vous liez la fonction bar à une autre variable est plus commun avec les callbacks), vous ne liez/passez pas la fonction avec son objet englobant mais seulement avec la fonction "nude" . Ainsi, avec la fonction "nude", this
désigne l’objet global.
Une petite démo
var foo = "global foo"; //foo set on the global object
var a = {foo : "object foo", bar : function(){return this.foo;}};
var bound = a.bar;
console.log(bound());//returns "global foo", not "object foo"
bound
il suffit de pointer vers le function(){return this.foo;}