我们知道函数声明是被提升的,你可以在脚本中的任何地方调用它们。对于函数表达式,情况并非如此。
例如:
test();
const test = () => {
console.log(1+3);
}
When we call test() it will always return undefined.
但是,当我们在expressjs中间件中调用相同的函数时,这种情况就不会发生。
router.get('/', (req, res, next) => {
test(); // it will return always the result 4
})
const test = () => {
console.log(1+3);
}
有人能给我解释一下为什么会这样吗?
发布于 2019-08-05 21:23:37
您的第一个代码片段在完全按照您显示的方式运行时,会生成以下错误:
ReferenceError: test is not defined
您的第二个代码片段之所以可以工作,是因为模块已经初始化,并且定义了const test
。一段时间后,路由回调被调用,test
现在被定义,并且在模块范围内有一个值。
对于let
和const
,在初始化之前在运行代码中引用它们是错误的。这就是为什么第一个代码片段会生成一个ReferenceError
。
但是,一旦初始化,它们就可以在定义它们的作用域内的任何地方使用。一些人称这是提升到范围的顶端。因为这与var
提升的工作方式不同,所以我只是认为,一旦定义了const
或let
符号,它就可以在其作用域内的任何地方使用,甚至可以在稍后调用的代码中使用,但在文件中出现得更早。这与Javascript的运行时变量查找是一致的。在第二个代码片段中执行路由处理程序时,将在其作用域内动态查找符号test
。由于在调用路由处理程序时,const test
已经运行并被初始化,因此它会找到一个已经初始化的test
变量,并且test()
工作得很好。
在您的第一个代码片段中,test
的动态查找失败,因为当您尝试调用test()
并创建ReferenceError
时,const test
尚未运行。
您可以在下面的代码中看到更简单的演示,它与您的第二个代码片段几乎相同:
function a() {
test();
}
const test = () => {
console.log(1+3);
}
a();
在这里,我们定义函数a
,然后将const test
定义为函数。然后,我们调用a()
,而后者又调用test()
。由于事件的顺序是:
test()
而且,所有的符号都可以从模块作用域访问,这样你就可以看到test
在被调用之前就已经定义好了,所以代码可以正常工作。
https://stackoverflow.com/questions/57365822
复制相似问题