tl; dr Se non chiami nulla finché non viene caricato tutto, dovresti stare bene.
Modifica: per una panoramica che copre anche alcune dichiarazioni ES6 ( let
, const
): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
Questo strano comportamento dipende da
- Come definire le funzioni e
- Quando li chiami.
Ecco alcuni esempi.
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();
Ciò è dovuto a qualcosa chiamato sollevamento !
Esistono due modi per definire le funzioni: dichiarazione di funzione ed espressione di funzione . La differenza è fastidiosa e minuscola, quindi diciamo solo questa cosa leggermente sbagliata: se la scrivi come function name() {}
, è una dichiarazione , e quando la scrivi come var name = function() {}
(o una funzione anonima assegnata a un ritorno, cose del genere), è un'espressione di funzione .
Per prima cosa, diamo un'occhiata a come vengono gestite le variabili:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Ora, come vengono gestite le dichiarazioni di funzione :
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
Le var
dichiarazioni "gettano" la creazione di foo
in alto, ma non le assegnano ancora il valore. La dichiarazione della funzione viene successiva nella riga e alla fine viene assegnato un valore foo
.
E questo?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Solo la dichiarazione di foo
viene spostata all'inizio. L'assegnazione avviene solo dopo che bar
è stata effettuata la chiamata a , dove si trovava prima che avvenisse tutto il sollevamento.
E infine, per concisione:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Ora, che dire delle espressioni di funzione ?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Proprio come le variabili regolari, prima foo
viene dichiarato nel punto più alto dell'ambito, quindi gli viene assegnato un valore.
Vediamo perché il secondo esempio genera un errore.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
Come abbiamo visto prima, foo
viene sollevata solo la creazione di , l'assegnazione arriva dove appariva nel codice "originale" (non sollevato). Quando bar
viene chiamato, è prima che gli foo
venga assegnato un valore, quindi foo === undefined
. Ora nel corpo della funzione di bar
, è come se lo stessi facendo undefined()
, il che genera un errore.