为什么函数表达式的位置在节点js中不重要?

时间:2015-12-07 16:47:45

标签: javascript node.js function-declaration hoisting function-expression

在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变量在使用之后被声明为,所以不应该抛出错误吗?

1 个答案:

答案 0 :(得分:3)

这有两个方面:

  1. 为什么传递给router.post的回调可以访问myFunc变量,当变量声明在代码中下面

  2. 为什么传递给router.post的回调可以访问分配给myFunc变量的函数,如果它没有分配给变量,直到下面它在代码中?

  3. 首先我们处理变量,然后我们将处理它的值(我们分配给它的函数):

      

    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的表达式)。

    例如,会发生什么:

    1. 准备工作(创建变体routermyFunc并将其设置为undefined

    2. express.Router来电,为router分配新值

    3. router.post的调用,传入但未调用回调函数

    4. 创建函数,为myFunc

      分配新值
    5. 稍后,当一个请求进入时,将调用回调,此时已创建myFunc(并且可以访问该回调,因为回调是关于myFunc所在的上下文的闭包声明)

    6. 这类似于:

      setTimeout(function() {
          var myVar = myFunc();
      }, 0);
      
      var myFunc = function() {
          // code here...
      }
      

      首先调用setTimeout,然后创建函数并将其分配给myFunc,然后调用回调函数并通过myFunc调用函数。