L'affirmation que j'ai faite à propos d'un JS non hissé incapable de prendre en charge la récurrence mutuelle est juste une conjecture à des fins d'illustration. Il est conçu pour aider à comprendre la nécessité pour le langage de connaître les variables disponibles dans le (s) domaine (s). Ce n'est pas une prescription pour un comportement linguistique exact. Une caractéristique de langage comme le levage - le fait de lever n'existe pas, c'est juste une métaphore pour les variables qui sont déclarées dans les environnements de portée à l'avance pendant la compilation, avant l'exécution - est une caractéristique tellement fondamentale qu'elle ne peut pas facilement être raisonnés lorsqu'ils sont séparés du reste des caractéristiques de la langue.
De plus, il est impossible de tester complètement cette hypothèse dans JS seulement. L'extrait de l'OP ne traite qu'une partie de l'équation, c'est-à-dire qu'elle utilise des expressions de fonction au lieu de déclarations de fonction pour éviter le levage de fonction. Le langage que j'utilisais pour comparer à l'illustration est C, qui exige par exemple que les signatures de fonction soient déclarées dans les fichiers d'en-tête .hh afin que le compilateur sache à quoi ressemble une fonction même si elle n'a pas "vu" encore. Sans cela, le compilateur étouffe. C'est une sorte de levage manuel dans un sens. C le fait pour la vérification de type, mais on peut imaginer que ce genre d'exigence existe pour d'autres raisons que cela.
Une autre façon de penser à ce sujet est de savoir si JS est un langage compilé où tout a été découvert avant qu'il exécute, ou si elle est interprété haut vers le bas en une seule passe. Si JS était interprété de manière descendante, et qu'il atteignait la définition d'une fonction a()
qui faisait référence à un b()
qu'il n'avait pas encore vu, cela pourrait poser problème. Si cette expression d'appel était traitée de manière non paresseuse, le moteur ne pouvait pas comprendre à ce moment-là à quoi servirait l'appel b()
, car b()
n'avait pas encore été traité. Certaines langues sont paresseuses et certaines sont non paresseuses.
En l'état, JS est compilé avant l'exécution, de sorte que le moteur a découvert toutes les fonctions (alias "levage") avant d'en exécuter aucune. JS traite aussi les expressions comme paresseuses, donc ensemble, cela explique pourquoi la récurrence mutuelle fonctionne bien. Mais si JS n'avait pas de levage et/ou n'était pas paresseux, on peut imaginer que le moteur JS serait incapable de gérer la récurrence mutuelle car la référence circulaire entre a()
et b()
signifierait en fait que l'un des deux a toujours été déclaré "trop tard".
C'est vraiment tout ce que je voulais dire dans le livre.
la seconde donnera une erreur si 'a (1)' est appelé avant les définitions de fonction. – gurvinder372
Oui, mais c'est trivialement vrai de toute fonction et son invocation (comme je le note dans la question). L'affirmation de Simpson semble être que la structure mutuellement récursive des fonctions nécessite un hissage, mais cela ne semble pas être le cas. – rswerve
Dans le premier, si vous donnez 'a (1)' avant la définition de la fonction, il ne donnera pas la même erreur. – gurvinder372