Perdonami se questo è il modo sbagliato di affrontare l'aggiunta di un punto. Non sono stato qui molto spesso e sarei lieto di ricevere indicazioni costruttive e / o critiche.
La risposta di Benjamin affronta la domanda dell'OP in modo eccellente, ma vorrei aggiungere una modifica che ci darà un giro completo del sollevamento e delle sue stranezze.
Se iniziamo il codice originale con una chiamata a f, in questo modo:
f();
var f = function() {
console.log("Me original.");
};
function f() {
console.log("Me duplicate.");
}
f();
L'output sarà quindi:
Me duplicate.
Me original.
Il motivo è che vare le functiondichiarazioni vengono sollevate in modi leggermente diversi.
Poiché varla dichiarazione viene spostata all'inizio dell'ambito corrente *, ma qualsiasi assegnazione non viene sollevata. Per quanto riguarda il valore della var dichiarata, è indefinito finché non viene raggiunta la riga di assegnazione originale.
Per le functiondichiarazioni , vengono issate sia la dichiarazione che la definizione. Le espressioni di funzione , come utilizzate nel var f = function() {...costrutto, non vengono sollevate.
Quindi, dopo il sollevamento, l'esecuzione è come se il codice fosse:
var f; // declares var f, but does not assign it.
// name and define function f, shadowing the variable
function f() {
console.log("Me duplicate.");
}
// call the currently defined function f
f();
// assigns the result of a function expression to the var f,
// which shadows the hoisted function definition once past this point lexically
f = function() {
console.log("Me original.");
}
// calls the function referenced by the var f
f();
* Tutto l'ambito JavaScript è lessicale, o funzione, ambito, ma a quel punto sembrava confondere le cose usare la parola f.