203 votes

Pourquoi puis-je utiliser une fonction avant qu'elle ne soit définie en JavaScript ?

Ce code fonctionne toujours, même dans des navigateurs différents :

function fooCheck() {
  alert(internalFoo()); // We are using internalFoo() here...

  return internalFoo(); // And here, even though it has not been defined...

  function internalFoo() { return true; } //...until here!
}

fooCheck();

Je n'ai cependant pas pu trouver une seule référence expliquant pourquoi cela devrait fonctionner. J'ai vu cela pour la première fois dans la note de présentation de John Resig, mais c'était seulement mentionné. Il n'y a pas d'explication, ni là, ni ailleurs d'ailleurs.

Quelqu'un pourrait-il m'éclairer ?

3 votes

Dans les nouvelles versions de Firefox, cela ne fonctionne pas si le code est dans un try/catch. Voir ce bidule : jsfiddle.net/qzzc1evt

255voto

bobince Points 270740

El function est magique et fait en sorte que son identifiant soit lié avant que tout ce qui se trouve dans son bloc de code* soit exécuté.

Cela diffère d'une affectation avec un function qui est évaluée dans l'ordre descendant normal.

Si vous changez l'exemple pour dire :

var internalFoo = function() { return true; };

il cessait de fonctionner.

La déclaration de fonction est syntaxiquement très distincte de l'expression de fonction, même si elles semblent presque identiques et peuvent être ambiguës dans certains cas.

Ceci est documenté dans le Norme ECMAScript , section 10.1.3 . Malheureusement, l'ECMA-262 n'est pas un document très lisible, même selon les normes en vigueur !

* : la fonction, le bloc, le module ou le script contenant.

0 votes

Je suppose que ce n'est vraiment pas lisible. Je viens de lire la section 10.1.3 que vous avez indiquée et je n'ai pas compris pourquoi les dispositions qui y figurent provoqueraient ce comportement. Merci pour l'information.

4 votes

@bobince Ok, j'ai commencé à douter de moi quand je n'ai pas trouvé une seule mention du terme "hissage" sur cette page. J'espère que ces commentaires ont suffisamment de Google Juice™ pour remettre les choses en place :).

2 votes

Il s'agit d'une combinaison question/réponse populaire. Pensez à le mettre à jour avec un lien/excerpt vers la spécification annotée ES5. (Qui est un peu plus accessible.)

15voto

le dorfier Points 27267

Le navigateur lit votre HTML du début à la fin et peut l'exécuter au fur et à mesure qu'il est lu et analysé en morceaux exécutables (déclarations de variables, définitions de fonctions, etc.) Mais à tout moment, il ne peut utiliser que ce qui a été défini dans le script avant ce point.

C'est différent des autres contextes de programmation qui traitent (compilent) tout votre code source, le lient éventuellement avec les bibliothèques dont vous avez besoin pour résoudre les références, et construisent un module exécutable, à partir duquel l'exécution commence.

Votre code peut faire référence à des objets nommés (variables, autres fonctions, etc.) qui sont définis plus loin, mais vous ne pouvez pas exécuter le code de référence tant que tous les éléments ne sont pas disponibles.

Au fur et à mesure que vous vous familiariserez avec JavaScript, vous deviendrez intimement conscient de la nécessité d'écrire les choses dans le bon ordre.

Révision : Pour confirmer la réponse acceptée (ci-dessus), utilisez Firebug pour parcourir la section script d'une page Web. Vous verrez qu'elle saute de fonction en fonction, ne visitant que la première ligne, avant d'exécuter réellement du code.

5voto

Toon Krijthe Points 36327

Dans certains langages, les identificateurs doivent être définis avant d'être utilisés. Une raison à cela est que le compilateur utilise un seul passage sur le code source.

Mais s'il y a plusieurs passages (ou si certains contrôles sont reportés), vous pouvez parfaitement vous passer de cette exigence. Dans ce cas, le code est probablement d'abord lu (et interprété), puis les liens sont établis.

2voto

RailsSon Points 3944

Je n'ai que peu utilisé JavaScript. Je ne suis pas sûr que cela puisse vous aider, mais cela ressemble beaucoup à ce dont vous parlez et peut vous donner un aperçu :

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/

0 votes

Le lien n'est plus mort.

4 votes

Le lien est mort.

0 votes

Voici un instantané d'archive.org. On dirait que l'auteur a pris en charge l'ensemble de leur site web pour avoir un contenu obsolète, bien que cet article de blog n'entre pas dans cette catégorie.

1voto

Aaron Digulla Points 143830

Le corps de la fonction "internalFoo" doit aller quelque part au moment de l'analyse syntaxique, de sorte que lorsque le code est lu (c'est-à-dire analysé) par l'interpréteur JS, la structure de données de la fonction est créée et le nom est attribué.

Ce n'est que plus tard, lors de l'exécution du code, que JavaScript essaie réellement de savoir si "internalFoo" existe, ce qu'il est et s'il peut être appelé, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X