返回后定义函数

时间:2014-11-14 10:16:03

标签: javascript angularjs closures standards-compliance

我目前正在阅读John Papa's AngularJS style guide并看到the code

function dataService() {
    var someValue = '';
    var service = {
        save: save,
        someValue: someValue,
        validate: validate
    };
    return service;

    ////////////

    function save() {
        /* */
    };

    function validate() {
        /* */
    };
}

您可以看到函数savevalidate在函数返回值后定义为。这是如何运作的?它是否符合标准并适用于所有浏览器(例如,来自IE 6)?

1 个答案:

答案 0 :(得分:11)

  

您可以看到函数savevalidate是在函数返回值后定义的。

这就是从它们写入的位置看起来的样子,是的,但实际上它们是在函数中的任何分步代码运行之前定义的。有时这被称为“将”声明“提升”到函数的顶部(类似的情况也发生在var;更多信息发生在下面)。

当控制进入执行上下文时(例如,当您输入一个函数时,在程序开头输入全局环境,或输入eval代码),这是之前发生的几个事情之一 执行的任何分步代码都是处理该上下文中的所有函数声明并创建这些函数。由于savevalidate是由函数声明定义的,因此它们是在代码的第一个逐步行之前创建的,因此它们在{ {1}}。

以下是调用函数时JavaScript引擎的作用(例如,调用return时),突出显示函数声明步骤:

  1. 设置dataService
  2. 的值
  3. 为呼叫创建一个新环境(让我们称之为this
  4. env上设置对函数[[Scope]]属性的引用(这是闭包工作方式的一部分)
  5. 为环境创建一个绑定对象(让我们称之为env)来保存我们由函数定义的各种名称(这是闭包如何工作的另一部分,以及如何变量引用已解决)
  6. 如果函数有名称,请将其作为引用函数
  7. 的属性添加到bindings
  8. 将正式函数参数添加到bindings
  9. 处理函数声明,将其名称添加到bindings
  10. 创建bindings对象,将其添加到arguments
  11. 将使用bindings声明的每个变量添加到var(如果尚未定义),其值为bindings
  12. 处理函数
  13. 中的逐步代码
  14. 设置调用表达式的结果
  15. 这在§10.4.1及其链接的部分中的规范中列出了极其详细的内容。 (如果你去阅读那个,自我鼓励,散文就是......不稳定......)这是当前规范的一个链接,但这在1999年旧版第三版规范的§10中也有明确规定,而且我很确定从一开始就是真的。

      

    它是否符合标准并适用于所有浏览器(例如,来自IE 6)?

    是。它曾经让我感到紧张,所以几年前(可能〜2005年)我在我能找到的所有当时和非常死的浏览器(包括IE6)上证明了这一点,并且它得到了普遍正确的处理。这实际上并不令人惊讶,因为这是使这段代码有效的原因:

    undefined

    ......人们一直这样做


    这种“提升”是函数声明和函数表达式之间的关键区别之一。如果doSomething(); function doSomething() { // .... } save是由函数表达式创建的,那么在validate之后编写它们会很重要 - 它们永远不会被创建在所有:

    return

    将创建// It wouldn't work like this, for instance function dataService() { var someValue = ''; var service = { save: save, // `save` has the value `undefined` at this point someValue: someValue, validate: validate // So does `validate` }; return service; //////////// var save = function() { // Now this is a function expression /* */ }; var validate = function() { // This too /* */ }; } save个变量(感谢上面的步骤9),但是在使用它们的地方,它们的值为validate并且所以返回的对象没用。