tl; dr Si vous n'appelez rien tant que tout n'est pas chargé, ça devrait aller.
Edit: Pour un aperçu qui couvre également certaines déclarations ES6 ( let
, const
): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
Ce comportement étrange dépend de
- Comment vous définissez les fonctions et
- Lorsque vous les appelez.
Voici quelques exemples.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
C'est à cause de quelque chose qui s'appelle le levage !
Il existe deux façons de définir des fonctions: la déclaration de fonction et l' expression de fonction . La différence est ennuyeuse et infime, alors disons simplement cette chose légèrement fausse: si vous l'écrivez comme function name() {}
, c'est une déclaration , et quand vous l'écrivez comme var name = function() {}
(ou une fonction anonyme affectée à un retour, des choses comme ça), c'est une expression de fonction .
Voyons d'abord comment les variables sont gérées:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Maintenant, comment les déclarations de fonction sont gérées:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
Les var
instructions "jettent" la création de foo
tout en haut, mais ne lui attribuent pas encore de valeur. La déclaration de fonction vient ensuite sur la ligne, et finalement une valeur est affectée à foo
.
Et qu'en est-il de ça?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Seule la déclaration de foo
est déplacée vers le haut. L'affectation intervient uniquement après l'appel à bar
, là où elle se trouvait avant que tout le levage ne se produise.
Et enfin, par concision:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Maintenant, qu'en est-il des expressions de fonction ?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Tout comme les variables régulières, la première foo
est déclarée au point le plus élevé de la portée, puis une valeur lui est attribuée.
Voyons pourquoi le deuxième exemple génère une erreur.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
Comme nous l'avons vu précédemment, seule la création de foo
est hissée, l'affectation vient là où elle apparaissait dans le code «original» (non hissé). Quand bar
est appelé, foo
une valeur lui est attribuée avant foo === undefined
. Maintenant, dans le corps de fonction de bar
, c'est comme si vous faisiez undefined()
, ce qui génère une erreur.