Ce code fonctionne toujours, même dans différents navigateurs:
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 trouvé une seule référence pour expliquer pourquoi cela devrait fonctionner. J'ai vu cela pour la première fois dans la note de présentation de John Resig, mais cela n'a été que mentionné. Il n'y a aucune explication là-bas ni nulle part d'ailleurs.
Quelqu'un pourrait-il m'éclairer.
javascript
function
Edu Felipe
la source
la source
Réponses:
La
function
déclaration est magique et oblige son identifiant à être lié avant que quoi que ce soit dans son bloc de code * soit exécuté.Cela diffère d'une affectation avec une
function
expression, qui est évaluée dans l'ordre descendant normal.Si vous avez changé l'exemple pour dire:
cela cesserait de fonctionner.
La déclaration de fonction est syntaxiquement assez 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 la norme ECMAScript , section 10.1.3 . Malheureusement, ECMA-262 n'est pas un document très lisible, même selon les standards-standards!
*: la fonction, le bloc, le module ou le script contenant.
la source
Cela s'appelle HOISTING - Invoquer (appeler) une fonction avant qu'elle n'ait été définie.
Deux types de fonctions différents sur lesquels je souhaite écrire sont:
Fonctions d'expression et fonctions de déclaration
Fonctions d'expression:
Les expressions de fonction peuvent être stockées dans une variable afin qu'elles n'aient pas besoin de noms de fonction. Ils seront également nommés comme une fonction anonyme (une fonction sans nom).
Pour invoquer (appeler) ces fonctions, elles ont toujours besoin d'un nom de variable . Ce type de fonction ne fonctionnera pas si elle est appelée avant d'avoir été définie, ce qui signifie que le levage ne se produit pas ici. Nous devons toujours définir la fonction d'expression d'abord, puis l'invoquer.
Voici comment vous pouvez l'écrire dans ECMAScript 6:
Fonctions de déclaration:
Les fonctions déclarées avec la syntaxe suivante ne sont pas exécutées immédiatement. Ils sont "enregistrés pour une utilisation ultérieure" et seront exécutés plus tard, lorsqu'ils seront appelés (appelés). Ce type de fonction fonctionne si vous l'appelez AVANT ou APRÈS où est défini. Si vous appelez une fonction de déclaration avant qu'elle n'ait été définie, le levage fonctionne correctement.
Exemple de levage:
la source
let fun = theFunction; fun(); function theFunction() {}
fonctionnera également (Nœud et navigateurs)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.
Ceci est différent des autres contextes de programmation qui traitent (compilent) tout votre code source, peut-être le lient avec toutes les bibliothèques dont vous avez besoin pour résoudre les références, et construisent un module exécutable, à quel point 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 de code de référence tant que toutes les pièces ne sont pas disponibles.
Au fur et à mesure que vous vous familiariserez avec JavaScript, vous deviendrez intimement conscient de votre besoin 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 de script d'une page Web. Vous le verrez passer d'une fonction à l'autre, ne visitant que la première ligne, avant d'exécuter réellement un code.
la source
Certaines langues exigent que les identifiants soient définis avant utilisation. Une raison à cela est que le compilateur utilise un seul passage sur le code source.
Mais s'il y a plusieurs passes (ou si certains contrôles sont reportés), vous pouvez parfaitement vivre sans cette exigence. Dans ce cas, le code est probablement d'abord lu (et interprété), puis les liens sont définis.
la source
Je n'ai utilisé que peu de JavaScript. Je ne sais pas si cela vous aidera, mais cela ressemble beaucoup à ce dont vous parlez et peut donner un aperçu:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
la source
Le corps de la fonction "internalFoo" doit aller quelque part au moment de l'analyse, donc lorsque le code est lu (aka parsing) 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, alors que le code est exécuté, JavaScript essaie réellement de savoir si "internalFoo" existe et de quoi il s'agit et s'il peut être appelé, etc.
la source
Pour la même raison, les éléments suivants seront toujours placés
foo
dans l'espace de noms global:la source
if
bloc ne crée pas de portée, tandis qu'unfunction()
bloc en crée toujours une. La vraie raison était que la définition des noms javascript globaux se produit lors de la phase de compilation, de sorte que même si le code ne s'exécute pas, le nom est défini. (Désolé, il a fallu si longtemps pour commenter)