Pour comprendre cela selon sa localisation, la situation peut être grossièrement divisée en trois types :
1. Dans les fonctions : il s'agit généralement d'un paramètre implicite.
2. En dehors de la fonction (dans le périmètre supérieur) : Dans le navigateur, cela fait référence à l'objet global dans Node.js, cela fait référence aux exports du module.
3. La chaîne passée à eval() : Si eval() est appelé directement, cela fait référence à l'objet courant ; si eval() est appelé indirectement, cela fait référence à l'objet global.
Nous avons effectué des tests correspondants pour ces catégories :
1. ceci dans la fonction
Les fonctions peuvent essentiellement représenter toutes les structures appelables dans JS, c'est donc le scénario le plus courant pour son utilisation, et les fonctions peuvent être divisées en trois rôles suivants :
Fonction réelle
Constructeur
Méthode
1.1 ceci
en fonctions réellesDans les fonctions réelles, la valeur de this est un modèle qui dépend du contexte dans lequel on la trouve.
Mode bâclé : il s'agit de l'objet global (fenêtre du navigateur).
Mode strict : la valeur de ceci n'est pas définie.
il s'agit d'un paramètre implicite de la fonction, donc sa valeur est toujours la même. Cependant, vous pouvez définir explicitement la valeur de this en utilisant la méthode call() ou apply().
1.2 this
dans le constructeurVous pouvez utiliser new pour utiliser une fonction comme constructeur. La nouvelle opération crée un nouvel objet et transmet cet objet au constructeur via celui-ci.
Le principe d'implémentation d'une nouvelle opération en JS est à peu près tel qu'indiqué dans le code suivant (veuillez voir ici pour une implémentation plus précise, cette implémentation est également plus compliquée) :
1.3 ceci
dans la méthodeL'utilisation de this dans les méthodes est plus encline aux langages traditionnels orientés objet : le récepteur pointé par this est l'objet qui contient cette méthode.
2. ceci dans le cadre
Dans le navigateur, la portée est la portée globale, et cela fait référence à l'objet global (tout comme la fenêtre) :
Dans Node.js, vous exécutez généralement des fonctions dans des modules. Par conséquent, la portée de niveau supérieur est une portée de module très spéciale :
3. ceci dans eval()
eval() peut être appelé directement (en appelant le nom de la fonction 'eval') ou indirectement (appelé par d'autres moyens, comme call()). Pour plus de détails, voir ici.
4. Pièges liés à cela
Vous devez faire attention aux 3 pièges liés à cela qui seront présentés ci-dessous. A noter que dans les exemples suivants, l'utilisation du mode Strict peut améliorer la sécurité du code. Puisque dans les fonctions réelles, la valeur de this n'est pas définie, vous recevrez un avertissement en cas de problème.
4.1 J'ai oublié d'utiliser new
Si vous n'utilisez pas new pour appeler le constructeur, alors vous utilisez en fait une vraie fonction. Ce ne sera donc pas la valeur attendue. En mode Sloppy, cela pointe vers la fenêtre et vous créerez des variables globales :
Si vous obtenez directement la valeur d'une méthode (sans l'appeler), vous utilisez la méthode comme une fonction. Vous ferez probablement cela lorsque vous souhaitez transmettre une méthode en tant que paramètre dans une fonction ou une méthode appelante. C'est le cas de setTimeout() et des gestionnaires d'événements enregistrés. J'utiliserai la méthode callIt() pour simuler ce scénario :
Si vous faites cela en mode Strict, ce n'est pas défini et vous n'obtiendrez toujours pas le résultat souhaité, mais au moins vous recevrez un avertissement :
Pour obtenir les résultats attendus, vous pouvez utiliser bind() :
bind() crée une autre fonction qui définit toujours la valeur de this sur counter.
4.3 Cacher ceci
Quand on utilise une fonction dans une méthode, on oublie souvent que la fonction a son propre this. Ceci est différent des méthodes, vous ne pouvez donc pas mélanger les deux. Pour plus de détails, veuillez consulter le code suivant :
3. Utilisez le deuxième paramètre de forEach. Le deuxième paramètre de forEach sera transmis à la fonction de rappel et utilisé comme celui-ci de la fonction de rappel.
5. Bonnes pratiques
Théoriquement, je pense que les fonctions réelles n'ont pas leur propre ceci, et la solution ci-dessus est également basée sur cette idée. ECMAScript 6 utilise des fonctions fléchées pour obtenir cet effet. Les fonctions fléchées sont des fonctions qui n'ont pas leur propre this. Dans une telle fonction, vous pouvez l'utiliser avec désinvolture et vous n'avez pas à vous soucier de son existence implicite.
Je n'aime pas que certaines API traitent cela comme un paramètre supplémentaire de la fonction réelle :