为什么 JavaScript 中没有挂起回调函数?
Why are callback functions not hoisted in JavaScript?
我理解 JavaScript 中变量和函数声明的概念被提升到封闭范围的顶部。但是如果我有一个命名的回调函数,它就不会被提升。我不明白为什么会这样。我在下面的代码 link 中解释了场景
示例:
function enclosingScope () {
var b;
function inner (def) {
def();
}
var a = 2;
}
// After hoisting due to compilation, the above changes to
function enclosingScope () {
// Function declarations are hoisted before variables
function inner (def) {
def();
}
var b, a;
a = 2
}
// But if I have a named callback, will that be hoisted?
function enclosingScope () {
function inner (def) {
def();
}
var b, a;
a = 2
inner(function cb () {
console.log('Test callback hoisting')
})
}
有问题的行为不限于命名回调。这是任何命名函数表达式的工作方式。考虑以下因素:
function foo() {
(function baz() { });
console.log(typeof baz);
}
> foo()
< undefined
baz
在它的体外是不可访问的。所以这是一个不同于提升的问题。
我觉得给出的答案太短了,所以这里有一个更规范的解释:
Javascript区分函数声明
function f() {}
和函数表达式
var f = function () {} // anynomous function or lambda
var g = function h() {} // named function expression
函数声明是语句,而函数表达式是...,你猜怎么着?耶,表情。请注意,命名函数表达式的名称(给定示例中的 h
)只能在函数体内部访问(给定示例中的 g
)。
只要您将函数声明嵌套在括号中,它就会自动转换为表达式。这意味着您的 function cb () {...}
只是一个命名函数表达式。但是你没有将它分配给一个变量,而是将它作为参数传递给 inner
.
当谈到与函数表达式相关的提升时,仅提升赋值变量的声明。函数声明不是这种情况:
console.log(f); // function f
console.log(g); // exists, but undefined
console.log(h); // reference error
function f() {}
var g = function h() {}
由于您的示例中的 cb
未分配给变量,因此无法提升。
因此这两行在提升方面是等价的:
inner(function cb(){});
(function cb(){});
奖金: const
/let
当您尝试调用用 const
或 let
声明的函数表达式时,然而,在其声明之前的词法上,会抛出一个引用错误:
console.log(g); // reference error
const g = function h() {}
g
也挂了。但是为了保护您免受意外 undefined
的影响。解释器抛出一个错误。我认为这是明智的。
我理解 JavaScript 中变量和函数声明的概念被提升到封闭范围的顶部。但是如果我有一个命名的回调函数,它就不会被提升。我不明白为什么会这样。我在下面的代码 link 中解释了场景
示例:
function enclosingScope () {
var b;
function inner (def) {
def();
}
var a = 2;
}
// After hoisting due to compilation, the above changes to
function enclosingScope () {
// Function declarations are hoisted before variables
function inner (def) {
def();
}
var b, a;
a = 2
}
// But if I have a named callback, will that be hoisted?
function enclosingScope () {
function inner (def) {
def();
}
var b, a;
a = 2
inner(function cb () {
console.log('Test callback hoisting')
})
}
有问题的行为不限于命名回调。这是任何命名函数表达式的工作方式。考虑以下因素:
function foo() {
(function baz() { });
console.log(typeof baz);
}
> foo()
< undefined
baz
在它的体外是不可访问的。所以这是一个不同于提升的问题。
我觉得给出的答案太短了,所以这里有一个更规范的解释:
Javascript区分函数声明
function f() {}
和函数表达式
var f = function () {} // anynomous function or lambda
var g = function h() {} // named function expression
函数声明是语句,而函数表达式是...,你猜怎么着?耶,表情。请注意,命名函数表达式的名称(给定示例中的 h
)只能在函数体内部访问(给定示例中的 g
)。
只要您将函数声明嵌套在括号中,它就会自动转换为表达式。这意味着您的 function cb () {...}
只是一个命名函数表达式。但是你没有将它分配给一个变量,而是将它作为参数传递给 inner
.
当谈到与函数表达式相关的提升时,仅提升赋值变量的声明。函数声明不是这种情况:
console.log(f); // function f
console.log(g); // exists, but undefined
console.log(h); // reference error
function f() {}
var g = function h() {}
由于您的示例中的 cb
未分配给变量,因此无法提升。
因此这两行在提升方面是等价的:
inner(function cb(){});
(function cb(){});
奖金: const
/let
当您尝试调用用 const
或 let
声明的函数表达式时,然而,在其声明之前的词法上,会抛出一个引用错误:
console.log(g); // reference error
const g = function h() {}
g
也挂了。但是为了保护您免受意外 undefined
的影响。解释器抛出一个错误。我认为这是明智的。