Может кто-нибудь объяснить эти определения функций и подъема?
Может кто-нибудь объяснить мне, что происходит в следующих трех примерах? Мои мысли для первого примера, bar
не выполняется (это просто объявление функции), поэтому, когда foo
выполняется, вывод undefined
? Для второго примера bar
выполняется так, что возвращается значение 3. Для третьего примера я понятия не имею, почему он производит 8.
// 1)
function foo() {
function bar() {
return 3;
}
}
foo(); // undefined
// 2)
function foo() {
function bar() {
return 3;
}
return bar();
}
foo(); // 3
// 3)
function foo(){
function bar(){
return 3;
}
return bar();
function bar() {
return 8;
}
}
foo(); // 8
6 ответов
Вы правы насчет примеров 1 и 2, поэтому я просто расскажу о примере 3.
Хотя, похоже, ты звонишь bar()
прежде чем переопределить его, function
декларации обрабатываются специально. Все функции определяются при первом входе в содержащую область, они не выполняются по порядку. Если у вас есть несколько объявлений для одной и той же функции, последняя является эффективной. Так что нет никакой разницы между:
function bar() {
// version 1
}
return bar();
function bar() {
// version 2
}
а также:
function bar() {
// version 2
}
return bar();
Таким образом, объявление функции отличается от назначения выражения функции переменной. Если бы вы вместо этого написали:
function foo() {
var bar = function() {
return 3;
}
return bar();
var bar = function() {
return 8;
}
}
foo();
тогда бы вернулся 3
,
Реальный ответ, который вы ищете, - подъем.
В третьем примере интерпретатор Javascript действительно выполняет:
var foo = function() {
var bar = function() {
return 3;
}
var bar = function() {
return 8;
}
return bar();
}
foo(); // 8
function
объявления обрабатываются в первую очередь в области действия функции, из которой они были вызваны. Я настоятельно рекомендую вам найти больше лекций о том, что такое подъем, в Javascript, например, вы можете начать с этого:
http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
Если функция с одинаковым именем и областью действия объявляется дважды, она игнорирует первую и выполняет вторую функцию. Вот что происходит #3.
Ваши предположения о первых двух примерах верны.
Последний пример возвращает 8
так как bar
пересматривается раньше foo
называется. Вот основной график событий:
foo
определеноbar
определяется как функция, которая возвращает3
bar
переопределяется как функция, которая возвращает8
foo
вызываетсяreturn
заявление ударил и переопределенbar
функция выполняется, возвращая8
Когда выполняется следующее, оба объявления функций поднимаются в верхнюю часть IIFE
область действия - вторая декларация, перекрывающая первую.
(function IIFE(){
function bar(){
return 3;
}
return bar();
function bar() {
return 8;
}
})()
(function IIFE(){
function bar(){
return 3;
}
function bar() {
return 8;
}
return bar();
})()
(function IIFE(){
function bar() {
return 8;
}
return bar();
})()
В вашем третьем примере bar()
объявляется дважды. Объявление, которое возвращает 8, объявляется последним, поэтому оно переопределяет bar()
и это объявление, которое выполняется.
function foo(){
function bar(){ // first declaration of bar()
return 3;
}
return bar(); // this executes the code in bar() as it was most recently redefined
function bar() { // second and last declaration of bar(); this redefines the
// first declaration
return 8;
}
}
foo(); // 8