web-dev-qa-db-fra.com

ES6 a immédiatement appelé la fonction flèche

Pourquoi cela fonctionne-t-il dans une console Node.js (testé dans les versions 4.1.1 et 5.3.0) mais ne fonctionne pas dans le navigateur (testé dans Chrome)? Ce bloc de code doit créer et appeler une fonction anonyme qui enregistre Ok.

() => {
  console.log('Ok');
}()

En outre, bien que ce qui précède fonctionne dans le nœud, cela ne fonctionne pas:

n => {
  console.log('Ok');
}()

Ni ceci:

(n) => {
  console.log('Ok');
}()

Ce qui est étrange, c’est que lorsque le paramètre est ajouté, il jette un SyntaxError sur la partie qui appelle immédiatement.

125
Cristy

Vous devez en faire une expression de fonction au lieu de la définition de fonction qui ne besoin d'un nom et en fait un JavaScript valide.

(() => {
  console.log('Ok');
})()

Est-ce que l'équivalent de IIFE

(function(){
   console.log('Ok')
})();

Et la raison possible pour laquelle cela fonctionne dans Node.js mais pas dans chrome est que son analyseur l'interprète comme une fonction à exécution automatique, comme ceci

function() { console.log('hello'); }();

fonctionne bien dans Node.js Ceci est une expression de fonction et chrome et firefox et la plupart des navigateurs l’interprètent de cette façon. Vous devez l'invoquer manuellement.

Le moyen le plus répandu d’indiquer à l’analyseur de s’attendre à une expression de fonction consiste à l’envelopper dans des parens, car en JavaScript, les parens ne peuvent pas contenir d’instruction. À ce stade, lorsque l’analyseur rencontre le mot clé function, il sait l’analyser comme une expression de fonction et non comme une déclaration de fonction.

En ce qui concerne la version paramétrée , cela fonctionnera.

((n) => {
  console.log('Ok');
})()
152
void

Aucune de celles-ci ne devrait fonctionner sans parenthèses.

Pourquoi?

Parce que selon les spécifications:

  1. ArrowFunction est listé sous AssignmentExpression
  2. Le LHS d'un CallExpression doit être un MemberExpression , SuperCall ou CallExpression

Ainsi, une ArrowFunction ne peut pas figurer sur le LHS d'un CallExpression .


Ce que cela signifie concrètement dans la manière dont => devrait être interprété, est que cela fonctionne au même niveau de niveau que les opérateurs d'affectation =, += etc.

Sens

  • x => {foo}() ne devient pas (x => {foo})()
  • L'interprète essaie de l'interpréter comme x => ({foo}())
  • Donc c'est toujours un SyntaxError
  • Donc, l’interprète décide que le ( doit être faux et jette un SyntaxError

Il y avait un bug sur Babel à ce sujet ici , aussi.

17
Paul S.

La raison pour laquelle vous rencontrez des problèmes de ce type est que la console elle-même tente d'imiter l'étendue globale du contexte que vous ciblez actuellement. Il essaie également de capturer les valeurs de retour des instructions et expressions que vous écrivez dans la console, de sorte que les résultats s'affichent. Prenez, par exemple:

> 3 + 2
< 5

Ici, il s’exécute comme s’il s’agissait d’une expression, mais vous l’écriviez comme s’il s’agissait d’une déclaration. Dans les scripts normaux, la valeur serait ignorée, mais ici, le code doit être mutilé en interne (comme encapsuler l’intégralité de l’instruction avec un contexte de fonction et une instruction return), ce qui provoque toutes sortes d’effets étranges, y compris les problèmes. vous vivez.

C'est également l'une des raisons pour lesquelles certains codes ES6 nus dans les scripts fonctionnent correctement, mais pas dans la console Chrome Dev Tools.

Essayez d’exécuter ceci dans la console Node et Chrome:

{ let a = 3 }

Dans Node ou dans une balise <script>, cela fonctionne très bien, mais dans la console, cela donne Uncaught SyntaxError: Unexpected identifier. Il vous donne également un lien vers la source sous la forme de VMxxx:1 sur lequel vous pouvez cliquer pour inspecter la source évaluée, qui se présente comme suit:

({ let a = 3 })

Alors pourquoi a-t-il fait cela?

La réponse est qu'il doit convertir votre code en une expression afin que le résultat puisse être renvoyé à l'appelant et affiché dans la console. Vous pouvez le faire en encapsulant l'instruction entre parenthèses, ce qui en fait une expression, mais rend également le bloc ci-dessus syntaxiquement incorrect (une expression ne peut pas avoir de déclaration de bloc).

La console essaie de résoudre ces problèmes Edge en faisant preuve de discernement dans le code, mais je pense que cela dépasse le cadre de cette réponse. Vous pouvez créer un bogue pour voir si cela pourrait être corrigé.

Voici un bon exemple de quelque chose de très similaire:

https://stackoverflow.com/a/28431346/46588

Le moyen le plus sûr de faire fonctionner votre code est de s’assurer qu’il peut être exécuté en tant qu’expression et inspecter le lien source SyntaxError pour voir quel est le code d’exécution réel et procéder au reverse engineering d’une solution. Cela signifie généralement une paire de parenthèses stratégiquement placées.

En bref: la console essaie d'imiter le contexte d'exécution global aussi précisément que possible, mais en raison des limitations d'interaction avec le moteur v8 et la sémantique JavaScript, cela est parfois difficile ou impossible à résoudre.

2
Klemen Slavič