Perdoe-me se esta é a maneira errada de abordar a adição de um ponto. Não tenho estado muito por aqui e gostaria de receber orientações e / ou críticas construtivas.
A resposta de Benjamin aborda a pergunta do OP de maneira excelente, mas eu gostaria de adicionar um ajuste que nos dará um tour completo de içamento e suas esquisitices.
Se começarmos o código original com uma chamada para f
, assim:
f();
var f = function() {
console.log("Me original.");
};
function f() {
console.log("Me duplicate.");
}
f();
A saída será:
Me duplicate.
Me original.
A razão é que var
efunction
declarações são levantadas de maneiras ligeiramente diferentes.
Para var
a declaração é movido para o topo do escopo atual *, mas qualquer atribuição não é içada. No que diz respeito ao valor do var declarado, ele é indefinido até que a linha de atribuição original seja alcançada.
Para function
declarações , tanto a declaração quanto a definição são suspensas. Expressões de função , conforme usadas novar f = function() {...
construção, não são içadas.
Portanto, após o içamento, a execução é como se o código 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();
* Todo escopo do JavaScript é léxico, ou função, escopo, mas parecia que apenas confundiria as coisas usar a palavra f naquele ponto.