在JavaScript中,当使用函数表达式(例如var myFunc = function() {...}
)时,与任何其他变量声明一样,您必须在使用它之前定义变量 。例如,以下示例将不工作(将导致Uncaught TypeError: myFunc is not a function
):
var myVar = myFunc();
var myFunc = function() {
// code here...
}
但是,在我的js项目的routes / index.js文件中,我有以下代码(显然缩写):
var router = express.Router();
.
.
.
router.post('/', function(req, res) {
...
...
var myVar = myFunc(); // WORKS!
...
...
}
var myFunc = function() {
...
}
myFunc
变量在使用之后被声明为,所以不应该抛出错误吗?
答案 0 :(得分:3)
这有两个方面:
为什么传递给router.post
的回调可以访问myFunc
变量,当变量声明在代码中下面
为什么传递给router.post
的回调可以访问分配给myFunc
变量的函数,如果它没有分配给变量,直到在下面它在代码中?
首先我们处理变量,然后我们将处理它的值(我们分配给它的函数):
myFunc变量在使用后声明,所以不应该抛出错误吗?
如果var
没有被吊起,那就好了。但var
已被提升。因此,当你的模块被加载时,首先 JavaScript引擎查看它以查找所有变量声明和函数声明,处理它们,然后然后执行逐步代码在你的模块中。
例如,对于JavaScript引擎,您的模块实际上如下所示:
var router = undefined;
var myFunc = undefined;
router = express.Router();
.
.
.
router.post('/', function(req, res) {
var myVar = undefined;
...
...
myVar = myFunc(); // WORKS!
...
...
}
myFunc = function() {
...
}
关于我的贫血小博客的更多信息:Poor misunderstood var
为什么在节点js中没有函数表达式的位置?
确实。您没有遇到麻烦的唯一原因是myFunc
在您调用router.post
的回调被调用之前未被使用, 在模块脚本的顶级范围代码之后(包括创建myFunc
的表达式)。
例如,会发生什么:
准备工作(创建变体router
和myFunc
并将其设置为undefined
)
express.Router
来电,为router
分配新值
对router.post
的调用,传入但未调用回调函数
创建函数,为myFunc
稍后,当一个请求进入时,将调用回调,此时已创建myFunc
(并且可以访问该回调,因为回调是关于myFunc
所在的上下文的闭包声明)
这类似于:
setTimeout(function() {
var myVar = myFunc();
}, 0);
var myFunc = function() {
// code here...
}
首先调用setTimeout
,然后创建函数并将其分配给myFunc
,然后调用回调函数并通过myFunc
调用函数。