La question s'adresse aux personnes qui ont pensé au style de code dans le contexte du prochain ECMAScript 6 (Harmony) et qui ont déjà travaillé avec le langage.
Avec () => {}
et function () {}
nous obtenons deux façons très similaires d'écrire des fonctions dans ES6. Dans d'autres langages, les fonctions lambda se distinguent souvent en étant anonymes, mais dans ECMAScript, toute fonction peut être anonyme. Chacun des deux types a des domaines d'utilisation uniques (à savoir quand this
doit être lié explicitement ou explicitement ne pas être lié). Entre ces domaines, il existe un grand nombre de cas où l'une ou l'autre notation fera l'affaire.
Les fonctions fléchées dans ES6 ont au moins deux limitations:
- Ne fonctionne pas avec
new
et ne peut pas être utilisé lors de la créationprototype
- Fixé
this
lié à la portée à l'initialisation
Ces deux limitations mises à part, les fonctions fléchées pourraient théoriquement remplacer les fonctions normales presque n'importe où. Quelle est la bonne approche en les utilisant dans la pratique? Les fonctions fléchées doivent-elles être utilisées, par exemple:
- "partout où ils fonctionnent", c'est-à-dire que partout où une fonction n'a pas à être agnostique à propos de la
this
variable et nous ne créons pas d'objet. - seulement "partout où ils sont nécessaires", c'est-à-dire les écouteurs d'événements, les délais d'attente, qui doivent être liés à une certaine portée
- avec des fonctions "courtes" mais pas avec des fonctions "longues"
- uniquement avec des fonctions qui ne contiennent pas d'autre fonction flèche
Ce que je recherche, c'est un guide pour sélectionner la notation de fonction appropriée dans la future version d'ECMAScript. La directive devra être claire, afin qu'elle puisse être enseignée aux développeurs dans une équipe, et être cohérente afin qu'elle ne nécessite pas de refactoring constant dans les deux sens d'une notation de fonction à l'autre.
Fixed this bound to scope at initialisation
comme une limitation?this
est quelque chose que vous pouvez faire avec des fonctions régulières mais pas avec des fonctions fléchées.Fixed this bound to scope at initialisation
soit une limitation. :) Jetez un oeil à cet article: exploringjs.com/es6/ch_arrow-functions.htmlRéponses:
Il y a quelque temps, notre équipe a migré tout son code (une application AngularJS de taille moyenne) vers JavaScript compilé à l'aide de
TraceurBabel . J'utilise maintenant la règle générale suivante pour les fonctions dans ES6 et au-delà:function
dans la portée globale et pour lesObject.prototype
propriétés.class
pour les constructeurs d'objets.=>
partout ailleurs.Pourquoi utiliser les fonctions fléchées presque partout?
thisObject
que la racine. Si même un seul rappel de fonction standard est mélangé à un tas de fonctions fléchées, il y a une chance que la portée devienne foirée.function
ressort immédiatement pour définir la portée. Un développeur peut toujours rechercher lafunction
déclaration suivante pour voir de quoi ilthisObject
s'agit.Pourquoi toujours utiliser des fonctions régulières sur la portée globale ou la portée du module?
thisObject
.window
objet (portée globale) est mieux adressé explicitement.Object.prototype
définitions ont une portée globale (pensez,String.prototype.truncate
etc.) et celles-ci doivent généralement être de typefunction
quand même. L'utilisation constantefunction
sur la portée globale permet d'éviter les erreurs.function foo(){}
queconst foo = () => {}
- en particulier en dehors des autres appels de fonction. (2) Le nom de la fonction apparaît dans les traces de pile. Bien qu'il soit fastidieux de nommer chaque rappel interne, nommer toutes les fonctions publiques est probablement une bonne idée.Constructeurs d'objets
La tentative d'instanciation d'une fonction flèche lève une exception:
Un avantage clé des fonctions par rapport aux fonctions fléchées est donc qu'elles fonctionnent comme des constructeurs d'objets:
Cependant, la définition de classe de brouillon 2 ES Harmony fonctionnellement identique est presque aussi compacte:
Je m'attends à ce que l'utilisation de l'ancienne notation soit finalement découragée. La notation du constructeur d'objet peut encore être utilisée par certains pour de simples usines d'objets anonymes où les objets sont générés par programme, mais pas pour beaucoup d'autre chose.
Lorsqu'un constructeur d'objet est nécessaire, il faut envisager de convertir la fonction en a
class
comme indiqué ci-dessus. La syntaxe fonctionne également avec les fonctions / classes anonymes.Lisibilité des fonctions fléchées
Le meilleur argument probablement pour s'en tenir aux fonctions régulières - que la sécurité de la portée soit maudite - serait que les fonctions fléchées sont moins lisibles que les fonctions régulières. Si votre code n'est pas fonctionnel en premier lieu, alors les fonctions fléchées peuvent ne pas sembler nécessaires, et lorsque les fonctions fléchées ne sont pas utilisées de manière cohérente, elles semblent laides.
ECMAScript a beaucoup changé depuis qu'ECMAScript 5.1 nous a donné la fonctionnalité
Array.forEach
,Array.map
et toutes ces fonctionnalités de programmation fonctionnelle qui nous font utiliser des fonctions où des boucles for auraient été utilisées auparavant. Le JavaScript asynchrone a beaucoup décollé. ES6 expédiera également unPromise
objet, ce qui signifie encore plus de fonctions anonymes. Il n'y a pas de retour en arrière pour la programmation fonctionnelle. En JavaScript fonctionnel, les fonctions fléchées sont préférables aux fonctions normales.Prenez par exemple ce morceau de code 3 (particulièrement déroutant) :
Le même morceau de code avec des fonctions régulières:
Alors que n'importe laquelle des fonctions fléchées peut être remplacée par une fonction standard, il y aurait très peu à gagner à le faire. Quelle version est plus lisible? Je dirais le premier.
Je pense que la question de l'utilisation des fonctions fléchées ou des fonctions régulières deviendra moins pertinente au fil du temps. La plupart des fonctions deviendront soit des méthodes de classe, qui font disparaître le
function
mot - clé, soit elles deviendront des classes. Les fonctions resteront utilisées pour patcher les classes via leObject.prototype
. En attendant, je suggère de réserver lefunction
mot - clé pour tout ce qui devrait vraiment être une méthode de classe ou une classe.Remarques
extend
mot - clé. Une différence mineure est que les déclarations de classe sont des constantes, contrairement aux déclarations de fonctions.la source
function
c'est quand vous ne voulezthis
pas être lié, non? Mon scénario le plus courant pour cela est les événements, où vous pouvezthis
faire référence à l'objet (généralement le nœud DOM) qui a déclenché l'événement.=>
finit par mieux paraître avec le temps. Je doute que les non-programmeurs ressentent très différemment les deux exemples. Si vous écrivez du code ES2016, vous n'allez pas non plus normalement utiliser ces nombreuses fonctions fléchées. Dans cet exemple, en utilisant async / wait et une compréhension de tableau, vous vous retrouveriez avec une seule fonction de flèche dans l'reduce()
appel.Selon la proposition , les flèches visaient "à aborder et à résoudre plusieurs points communs douloureux du traditionnel
Function Expression
". Ils avaient l'intention d'améliorer les choses en liantthis
lexicalement et en offrant une syntaxe concise.cependant,
this
lexicalementPar conséquent, les fonctions fléchées créent des opportunités de confusion et d'erreurs et doivent être exclues du vocabulaire d'un programmeur JavaScript, remplacées par
function
exclusivement.Concernant lexical
this
this
est problématique:Les fonctions fléchées visent à résoudre le problème où nous devons accéder à une propriété de l'
this
intérieur d'un rappel. Il y a déjà plusieurs façons de le faire: On pourrait assignerthis
à une variable, utiliserbind
ou utiliser le 3e argument disponible sur lesArray
méthodes d'agrégation. Pourtant, les flèches semblent être la solution de contournement la plus simple, donc la méthode pourrait être refactorisée comme ceci:Cependant, considérez si le code a utilisé une bibliothèque comme jQuery, dont les méthodes se lient
this
spécialement. Maintenant, il y a deuxthis
valeurs à gérer:Nous devons utiliser
function
afineach
de lierthis
dynamiquement. Nous ne pouvons pas utiliser de fonction de flèche ici.Gérer plusieurs
this
valeurs peut également être source de confusion, car il est difficile de savoir de quelthis
auteur parlait:L'auteur avait-il réellement l'intention d'appeler
Book.prototype.reformat
? Ou a-t-il oublié de se lierthis
et avait-il l'intention d'appelerReader.prototype.reformat
? Si nous changeons le gestionnaire en une fonction de flèche, nous nous demanderons également si l'auteur voulait la dynamiquethis
, mais a choisi une flèche car elle tient sur une seule ligne:On peut se poser la question suivante: "Est-il exceptionnel que les flèches soient parfois la mauvaise fonction à utiliser? Peut-être que si nous n'avons que rarement besoin de
this
valeurs dynamiques , il serait toujours acceptable d'utiliser des flèches la plupart du temps."Mais demandez-vous ceci: «Serait-il« utile »de déboguer du code et de découvrir que le résultat d'une erreur a été provoqué par un« cas de bord »?» «Je préfère éviter les problèmes non seulement la plupart du temps, mais 100% du temps.
Il y a une meilleure façon: toujours utiliser
function
(doncthis
peut toujours être lié dynamiquement), et toujours référencerthis
via une variable. Les variables sont lexicales et prennent plusieurs noms. L'affectationthis
à une variable rendra vos intentions claires:De plus, toujours assigner
this
à une variable (même quand il y a une seulethis
ou aucune autre fonction) garantit que ses intentions restent claires même après que le code est changé.De plus, la dynamique
this
n'est guère exceptionnelle. jQuery est utilisé sur plus de 50 millions de sites Web (au moment de la rédaction de ce rapport en février 2016). Voici d'autres API liantthis
dynamiquement:this
.this
.this
.EventTarget
avecthis
.this
.(Statistiques via http://trends.builtwith.com/javascript/jQuery et https://www.npmjs.com .)
Il est probable que vous
this
ayez déjà besoin de liaisons dynamiques .Un lexical
this
est parfois attendu, mais parfois non; tout comme une dynamiquethis
est parfois attendue, mais parfois non. Heureusement, il existe un meilleur moyen, qui produit et communique toujours la liaison attendue.Concernant la syntaxe laconique
Les fonctions fléchées ont réussi à fournir une "forme syntaxique plus courte" pour les fonctions. Mais ces fonctions plus courtes vous rendront-elles plus efficaces?
Est
x => x * x
"plus facile à lire" quefunction (x) { return x * x; }
? C'est peut-être le cas, car il est plus susceptible de produire une seule ligne de code courte. Accor à Dyson L'influence de la vitesse de lecture et de la longueur de ligne sur l'efficacité de la lecture à l'écran ,Des justifications similaires sont faites pour l'opérateur conditionnel (ternaire) et pour les
if
instructions sur une seule ligne .Cependant, écrivez- vous vraiment les fonctions mathématiques simples annoncées dans la proposition ? Mes domaines ne sont pas mathématiques, donc mes sous-programmes sont rarement aussi élégants. Au contraire, je vois souvent que les fonctions fléchées dépassent une limite de colonne et se terminent par une autre ligne en raison de l'éditeur ou du guide de style, ce qui annule la «lisibilité» selon la définition de Dyson.
On pourrait se poser la question: «Que diriez-vous d'utiliser la version courte pour les fonctions courtes, lorsque cela est possible? Mais maintenant, une règle stylistique contredit une contrainte de langage: "Essayez d'utiliser la notation de fonction la plus courte possible, en gardant à l'esprit que parfois seule la notation la plus longue se liera
this
comme prévu." Cette confusion rend les flèches particulièrement susceptibles d'être utilisées à mauvais escient.Il existe de nombreux problèmes avec la syntaxe de la fonction flèche:
Ces deux fonctions sont syntaxiquement valides. Mais ce
doSomethingElse(x);
n'est pas dans le corps deb
, c'est juste une déclaration de haut niveau mal indentée.Lors de l'expansion vers la forme bloc, il n'y a plus d'implicite
return
, que l'on pourrait oublier de restaurer. Mais l'expression n'a peut- être été conçue que pour produire un effet secondaire, alors qui sait si une explicitereturn
sera nécessaire à l'avenir?Ce qui peut être prévu comme paramètre de repos peut être analysé en tant qu'opérateur d'étalement:
L'affectation peut être confondue avec les arguments par défaut:
Les blocs ressemblent à des objets:
Qu'est-ce que ça veut dire?
L'auteur avait-il l'intention de créer un no-op, ou une fonction qui renvoie un objet vide? (Dans cet esprit, devrions-nous jamais placer
{
après=>
? Devrions-nous nous limiter à la syntaxe d'expression uniquement? Cela réduirait davantage la fréquence des flèches.)=>
ressemble<=
et>=
:Pour invoquer une expression de fonction flèche immédiatement, il faut placer
()
à l'extérieur, mais placer()
à l'intérieur est valide et peut être intentionnel.Bien que, si l'on écrit
(() => doSomething()());
avec l'intention d'écrire une expression de fonction immédiatement invoquée, rien ne se passera.Il est difficile de prétendre que les fonctions fléchées sont "plus compréhensibles" compte tenu des cas ci-dessus. On pourrait apprendre toutes les règles spéciales requises pour utiliser cette syntaxe. ça en vaut vraiment la peine?
La syntaxe de
function
est généralisée sans exception. Utiliserfunction
exclusivement signifie que le langage lui-même empêche d'écrire du code déroutant. Pour écrire des procédures qui doivent être comprises syntaxiquement dans tous les cas, je choisisfunction
.Concernant une ligne directrice
Vous demandez une ligne directrice qui doit être "claire" et "cohérente". L'utilisation des fonctions fléchées aboutira finalement à un code syntaxiquement valide et logiquement invalide, les deux formes de fonction étant entrelacées, de manière significative et arbitraire. Par conséquent, j'offre ce qui suit:
Directive pour la notation des fonctions dans ES6:
function
.this
à une variable. Ne pas utiliser() => {}
.la source
self
au lieu d'un ceci. Vos pièges de fonction de flèche indiqués sont également tous valides, et les mêmes normes que sur d'autres déclarations qui peuvent aller sans accolades s'appliquent également ici; sinon, je pense qu'avec votre argument, on pourrait tout aussi bien défendre les fonctions fléchées partout.this
est le problème de Javascript. Au lieu d'être implicitement lié,this
doit être passé comme argument explicite.Les fonctions fléchées ont été créées pour simplifier la fonction
scope
et résoudre lethis
mot - clé en le rendant plus simple. Ils utilisent la=>
syntaxe, qui ressemble à une flèche.Remarque: il ne remplace pas les fonctions existantes. Si vous remplacez chaque syntaxe de fonction par des fonctions fléchées, cela ne fonctionnera pas dans tous les cas.
Jetons un coup d'œil à la syntaxe ES5 existante. Si le
this
mot - clé était à l'intérieur de la méthode d'un objet (une fonction qui appartient à un objet), à quoi se référerait-il?L'extrait ci-dessus fait référence à un
object
et imprime le nom"RajiniKanth"
. Explorons l'extrait ci-dessous et voyons ce que cela signifierait ici.Et maintenant, si le
this
mot - clé était à l'intérieur demethod’s function
?Ici, cela ferait référence à
window object
lainner function
comme à sa pertescope
. Carthis
, fait toujours référence au propriétaire de la fonction dans laquelle il se trouve, dans ce cas - puisqu'il est désormais hors de portée - l'objet window / global.Lorsqu'il se trouve à l'intérieur d'une
object
méthode, lefunction
propriétaire de l'objet est l'objet. Ainsi, le mot-clé this est lié à l'objet. Pourtant, lorsqu'il se trouve à l'intérieur d'une fonction, qu'il soit autonome ou dans une autre méthode, il se référera toujours à l'window/global
objet.Il existe des moyens de résoudre ce problème en
ES5
soi, examinons cela avant de plonger dans les fonctions fléchées ES6 pour savoir comment le résoudre.En règle générale, vous créez une variable en dehors de la fonction interne de la méthode. Maintenant , les
‘forEach’
gains de la méthode d' accès àthis
et ainsi lesobject’s
propriétés et leurs valeurs.utiliser
bind
pour attacher lethis
mot-clé qui fait référence à la méthode au fichiermethod’s inner function
.Maintenant, avec la
ES6
fonction flèche, nous pouvons traiter lelexical scoping
problème de manière plus simple.Arrow functions
sont plus comme des instructions de fonction, sauf qu’ellesbind
le fontparent scope
. Si learrow function is in top scope
, l'this
argument fera référence àwindow/global scope
, tandis qu'une fonction de flèche à l' intérieur d' une fonction régulière aura son argument le même que sa fonction extérieure.Avec les
arrow
fonctionsthis
est lié à l'enveloppescope
au moment de la création et ne peut pas être modifié. Le nouvel opérateur, bind, call et apply n'ont aucun effet sur cela.Dans l'exemple ci-dessus, nous avons perdu le contrôle de cela. Nous pouvons résoudre l'exemple ci-dessus en utilisant une référence variable de
this
ou en utilisantbind
. Avec ES6, il devient plus facile de gérer lethis
comme il se doitlexical scoping
.Quand ne pas utiliser les fonctions Flèche
À l'intérieur d'un objet littéral.
Actor.getName
est défini avec une fonction de flèche, mais lors de l'invocation, il alerte non défini car ilthis.name
resteundefined
le contextewindow
.Cela se produit parce que la fonction flèche lie le contexte lexicalement avec la
window object
portée externe ... ie. L'exécutionthis.name
est équivalente àwindow.name
, ce qui n'est pas défini.Prototype d'objet
La même règle s'applique lors de la définition de méthodes sur un
prototype object
. Au lieu d'utiliser une fonction de flèche pour définir la méthode sayCatName, ce qui apporte une erreurcontext window
:Invoquer des constructeurs
this
dans une invocation de construction est l'objet nouvellement créé. Lors de l'exécution de la nouvelle Fn (), le contexte de laconstructor Fn
est un nouvel objet:this instanceof Fn === true
.this
est configuré à partir du contexte englobant, c'est-à-dire la portée externe qui le rend non affecté à un objet nouvellement créé.Rappel avec contexte dynamique
La fonction flèche lie
context
statiquement la déclaration et n'est pas possible de la rendre dynamique. Attacher des écouteurs d'événements aux éléments DOM est une tâche courante dans la programmation côté client. Un événement déclenche la fonction de gestionnaire avec ceci comme élément cible.this
est une fenêtre dans une fonction de flèche définie dans le contexte global. Lorsqu'un événement de clic se produit, le navigateur tente d'appeler la fonction de gestionnaire avec le contexte du bouton, mais la fonction flèche ne change pas son contexte prédéfini.this.innerHTML
est équivalentwindow.innerHTML
et n'a aucun sens.Vous devez appliquer une expression de fonction, ce qui permet de changer cela en fonction de l'élément cible:
Lorsque l'utilisateur clique sur le bouton, celui-ci dans la fonction de gestionnaire est le bouton.
this.innerHTML = 'Clicked button'
Modifie ainsi correctement le texte du bouton pour refléter l'état cliqué.Références: https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
la source
using bind to attach the this keyword that refers to the method to the method’s inner function.
a des erreurs de syntaxe.var Actor = { name: 'RajiniKanth', movies: ['Kabali', 'Sivaji', 'Baba'], showMovies: function() { this.movies.forEach(function(movie){ alert(this.name + ' has acted in ' + movie); }.bind(this)) } }; Actor.showMovies();
Utilisation: toutes les fonctions ES5 doivent être remplacées par des fonctions fléchées ES6, sauf dans les scénarios suivants:
Les fonctions fléchées ne doivent PAS être utilisées:
this
/arguments
dans une fonctionthis
/arguments
d'elles-mêmes, elles dépendent de leur contexte extérieur.constructor
this
.this
(qui devrait être l'objet lui-même).Comprenons certaines des variantes des fonctions fléchées pour mieux comprendre:
Variante 1 : lorsque nous voulons passer plusieurs arguments à une fonction et en renvoyer une valeur.
Version ES5 :
Version ES6 :
Remarque: le
function
mot clé n'est PAS requis.=>
est requis.{}
sont facultatifs, lorsque nous ne fournissons pas{}
return
est implicitement ajouté par JavaScript et lorsque nous fournissons,{}
nous devons ajouterreturn
si nous en avons besoin.Variante 2 : lorsque nous voulons passer un seul argument à une fonction et en renvoyer une valeur.
Version ES5 :
Version ES6 :
Remarque: Lorsque vous passez un seul argument, nous pouvons omettre les parenthèses
()
.Variante 3 : lorsque nous ne voulons PAS passer d'argument à une fonction et ne voulons pas retourner de valeur.
Version ES5 :
Version ES6 :
Variante 4 : lorsque nous voulons revenir explicitement des fonctions fléchées.
Version ES6 :
Variante 5 : lorsque nous voulons renvoyer un objet à partir des fonctions fléchées.
Version ES6 :
Remarque: Nous devons encapsuler l'objet entre parenthèses,
()
sinon JavaScript ne peut pas faire la différence entre un bloc et un objet.Variante 6 : Les fonctions fléchées n'ont PAS
arguments
(un objet de type tableau) qui leur sont propres, elles dépendent du contexte extérieur pourarguments
.Version ES6 :
Note:
foo
est une fonction ES5, avec unarguments
tableau comme objet et un argument qui lui est passé est2
doncarguments[0]
pourfoo
est 2.abc
est une fonction ES6 flèche car il ne dispose pas de son proprearguments
où elle imprimearguments[0]
defoo
ce contexte extérieur de la place.Variante 7 : Les fonctions fléchées n'ont PAS
this
leur propre fonction, elles dépendent du contexte extérieur pourthis
Version ES5 :
Remarque: Le rappel passé à setTimeout est une fonction ES5 et elle a sa propre
this
qui n'est pas définie dans l'use-strict
environnement, donc nous obtenons une sortie:Version ES6 :
Remarque: Le rappel est passé à
setTimeout
est une fonction ES6 flèche et il ne dispose pas de son proprethis
il qu'il faut à partir de son contexte extérieur qui est cegreetUser
qui athis
qui est parobj6
conséquent nous obtenons sortie:Divers: Nous ne pouvons pas utiliser les
new
fonctions fléchées. Les fonctions fléchées n'ont pas deprototype
propriété. Nous n'avons PAS de liaisonthis
lorsque la fonction flèche est invoquée viaapply
oucall
.la source
En plus des excellentes réponses jusqu'à présent, je voudrais présenter une raison très différente pour laquelle les fonctions fléchées sont dans un certain sens fondamentalement meilleures que les fonctions JavaScript "ordinaires". Pour les besoins de la discussion, supposons temporairement que nous utilisons un vérificateur de type tel que TypeScript ou "Flow" de Facebook. Considérez le module jouet suivant, qui est un code ECMAScript 6 valide plus des annotations de type Flow: (Je vais inclure le code non typé, qui résulterait de manière réaliste de Babel, à la fin de cette réponse, afin qu'il puisse réellement être exécuté.)
Voyons maintenant ce qui se passe lorsque nous utilisons la classe C à partir d'un module différent, comme ceci:
Comme vous pouvez le voir, le vérificateur de type a échoué ici: f2 était censé retourner un nombre, mais il a renvoyé une chaîne!
Pire encore, il semble qu'aucun vérificateur de type concevable ne puisse gérer les fonctions JavaScript ordinaires (sans flèche), car le "this" de f2 ne se produit pas dans la liste d'arguments de f2, donc le type requis pour "this" n'a pas pu être ajouté. comme une annotation à f2.
Ce problème affecte-t-il également les personnes qui n'utilisent pas de vérificateurs de type? Je pense que oui, car même lorsque nous n'avons pas de types statiques, nous pensons qu'ils sont là. ("Les premiers paramètres doivent être un nombre, le second une chaîne", etc.) Un argument "ce" caché qui peut ou non être utilisé dans le corps de la fonction rend notre comptabilité mentale plus difficile.
Voici la version exécutable non typée, qui serait produite par Babel:
la source
Je reste fidèle à tout ce que j'ai écrit dans ma première réponse dans ce fil. Cependant, mon opinion sur le style de code s'est développée depuis lors, j'ai donc une nouvelle réponse à cette question qui s'appuie sur ma dernière.
Concernant lexical
this
Dans ma dernière réponse, j'ai délibérément renoncé à une croyance sous-jacente que j'ai au sujet de cette langue, car elle n'était pas directement liée à l'argument que je faisais. Néanmoins, sans que cela soit explicitement indiqué, je peux comprendre pourquoi beaucoup de gens rechignent simplement à ma recommandation de ne pas utiliser de flèches, quand ils trouvent les flèches si utiles.
Ma conviction est la suivante: nous ne devrions pas utiliser
this
en premier lieu. Par conséquent, si une personne évite délibérément d'utiliserthis
dans son code, lathis
caractéristique «lexicale » des flèches est de peu ou pas de valeur. De plus, selon la prémisse quithis
est une mauvaise chose, le traitement de Arrowthis
est moins une «bonne chose»; il s'agit plutôt d'une forme de contrôle des dommages pour une autre fonctionnalité de langage incorrect.Je pense que cela non plus ne se produit pas pour certaines personnes, mais même pour ceux à qui cela se produit, ils doivent toujours se retrouver à travailler dans des bases de code où
this
apparaît cent fois par fichier, et un peu (ou beaucoup) de contrôle des dommages est tout. une personne raisonnable pouvait espérer. Les flèches peuvent donc être bonnes, d'une certaine manière, lorsqu'elles améliorent une mauvaise situation.Même s'il est plus facile d'écrire du code avec
this
des flèches que sans elles, les règles d'utilisation des flèches restent très complexes (voir: thread actuel). Ainsi, les directives ne sont ni «claires» ni «cohérentes», comme vous l'avez demandé. Même si les programmeurs connaissent les ambiguïtés des flèches, je pense qu'elles haussent les épaules et les acceptent quand même, car la valeur du lexical lesthis
éclipse.Tout cela est une préface à la réalisation suivante: si l'on n'utilise pas
this
, alors l'ambiguïté à propos de cethis
que les flèches provoquent normalement devient inutile. Les flèches deviennent plus neutres dans ce contexte.Concernant la syntaxe laconique
Lorsque j'ai écrit ma première réponse, j'étais d'avis que même l'adhésion servile aux meilleures pratiques était un prix intéressant à payer si cela signifiait que je pouvais produire un code plus parfait. Mais j'ai finalement réalisé que la concision peut également servir de forme d'abstraction qui peut également améliorer la qualité du code - suffisamment pour justifier parfois de s'écarter des meilleures pratiques.
En d'autres termes: bon sang, je veux aussi des fonctions à une ligne!
Concernant une ligne directrice
Avec la possibilité de
this
fonctions de flèche -neutre et la justesse valant la peine d'être poursuivie, j'offre la ligne directrice plus clémente suivante:Directive pour la notation des fonctions dans ES6:
this
.la source
Je préfère utiliser les fonctions de flèche à tout moment où l'accès au local
this
n'est pas nécessaire, car la fonction de flèche ne lie pas ses propres arguments this, arguments, super ou new.target .la source
D'une manière simple,
Un autre exemple:
Rép: La console afficherait 20.
La raison étant que chaque fois qu'une fonction est exécutée, sa propre pile est créée, dans cet exemple, la
ex
fonction est exécutée avec l'new
opérateur afin qu'un contexte soit créé, et quand ilinner
est exécuté, JS crée une nouvelle pile et exécute lainner
fonction aglobal context
bien qu'il y ait un contexte local.Donc, si nous voulons que la
inner
fonction ait un contexte local,ex
alors nous devons lier le contexte à la fonction interne.Les flèches résolvent ce problème, au lieu de prendre le,
Global context
ils prennent lelocal context
s'il existe. Dans legiven example,
cela prendranew ex()
commethis
.Ainsi, dans tous les cas où la liaison est explicite, les flèches résolvent le problème par défaut.
la source
Les fonctions fléchées ou Lambdas, ont été introduites dans ES 6. Outre son élégance dans la syntaxe minimale, la différence fonctionnelle la plus notable est la portée de l'
this
intérieur d'une fonction fléchéeLimitations Fonctions fléchées comme méthodes sur un objet
Dans le cas
objA.print()
où laprint()
méthode définie à l'aide de regularfunction
, cela fonctionnait en se résolvantthis
correctement à l'objA
invocation de la méthode mais échouait lorsqu'elle était définie comme une=>
fonction de flèche . C'est parce quethis
dans une fonction régulière lorsqu'elle est invoquée comme méthode sur un objet (objA
), c'est l'objet lui-même. Cependant, dans le cas d'une fonction flèche,this
se lie lexicalement à l'this
étendue englobante où elle a été définie (global / Window dans notre cas) et reste la même pendant son invocation en tant que méthodeobjA
.Avantages des fonctions fléchées par rapport aux fonctions régulières dans les méthodes d'un objet MAIS uniquement lorsque l'
this
on s'attend à ce qu'il soit fixé et lié à la définition de l'heure.Dans le cas
objB.print()
où laprint()
méthode est définie comme une fonction qui appelleconsole.log(
[$ {this.id} -> {this.name}] de)
manière asynchrone comme rappelsetTimeout
,this
résolue correctementobjB
lorsqu'une fonction de flèche a été utilisée comme rappel mais a échoué lorsque le rappel a été défini comme une fonction régulière. C'est parce que la=>
fonction de flèche est passée àsetTimeout(()=>..)
fermée surthis
lexicalement de son parent ie. invocationobjB.print()
qui l'a défini. En d'autres termes, la=>
fonction flèche est passée à àsetTimeout(()==>...
liée àobjB
car c'estthis
parce que l'invocation deobjB.print()
this
étaitobjB
elle-même.Nous pourrions facilement utiliser
Function.prototype.bind()
, pour faire fonctionner le rappel défini comme une fonction régulière, en le liant à la bonnethis
.Cependant, les fonctions fléchées sont utiles et moins sujettes aux erreurs dans le cas des rappels asynchrones où nous connaissons
this
au moment de la définition des fonctions auxquelles elles sont et doivent être liées.Limitation des fonctions fléchées là où cela doit changer d'une invocation à l'autre
À tout moment, nous avons besoin d'une fonction qui
this
peut être modifiée au moment de l'invocation, nous ne pouvons pas utiliser les fonctions fléchées.Rien de ce qui précède ne fonctionnera avec la fonction flèche
const print = () => { console.log(
[$ {this.id} -> {this.name}]);}
car ellethis
ne peut pas être modifiée et restera liée à lathis
portée englobante où elle a été définie (global / Window). Dans tous ces exemples, nous avons invoqué la même fonction avec des objets différents (obj1
etobj2
) l'un après l'autre, tous deux créés après laprint()
déclaration de la fonction.Ce sont des exemples artificiels, mais réfléchissons à des exemples plus réels. Si nous devions écrire notre
reduce()
méthode de manière similaire à celle qui fonctionnearrays
, nous ne pouvons pas la définir à nouveau comme un lambda, car elle doit être déduitethis
du contexte d'invocation, c'est-à-dire. le tableau sur lequel il a été invoquéPour cette raison, les
constructor
fonctions ne peuvent jamais être définies comme des fonctions flèches, commethis
pour une fonction constructeur ne peut pas être définie au moment de sa déclaration. Chaque fois qu'une fonction constructeur est invoquée avec unnew
mot clé, un nouvel objet est créé qui est ensuite lié à cette invocation particulière.De plus, lorsque les frameworks ou les systèmes acceptent une ou plusieurs fonctions de rappel à invoquer ultérieurement avec un contexte dynamique
this
, nous ne pouvons pas utiliser les fonctions fléchées, car ilthis
peut encore être nécessaire de changer à chaque appel. Cette situation se produit généralement avec les gestionnaires d'événements DOMC'est aussi la raison pour laquelle dans des cadres comme Angular 2+ et Vue.js s'attendent à ce que les méthodes de liaison de composant de modèle soient des fonctions / méthodes régulières
this
car leur invocation est gérée par les cadres pour les fonctions de liaison. (Angular utilise Zone.js pour gérer le contexte asynchrone pour les appels de fonctions de liaison de modèle de vue).D'autre part, dans React , lorsque nous voulons passer la méthode d'un composant en tant que gestionnaire d'événements par exemple,
<input onChange={this.handleOnchange} />
nous devons définirhandleOnchanage = (event)=> {this.props.onInputChange(event.target.value);}
comme une fonction de flèche comme pour chaque invocation, nous voulons que ce soit la même instance du composant qui a produit le JSX pour le rendu Élément DOM.Cet article est également disponible sur ma publication Medium . Si vous aimez l'artile, ou si vous avez des commentaires et suggestions, veuillez applaudir ou laisser des commentaires sur Medium .
la source