【问题标题】:Defining functions after return返回后定义函数
【发布时间】:2015-01-11 16:54:15
【问题描述】:

我目前正在阅读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 开始)?

【问题讨论】:

标签: javascript angularjs closures standards-compliance


【解决方案1】:

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

这就是它们的编写位置,是的,但实际上它们是在函数中的任何分步代码运行之前定义的。有时这被称为将声明“提升”到函数顶部(var 也会发生类似的情况;更多内容见下文)。

当控件进入执行上下文时(例如,当你进入一个函数时,进入程序开头的全局环境,或者输入eval代码),发生的几件事之一之前 em> 执行任何一步一步的代码都是处理该上下文中的所有函数声明并创建这些函数。由于savevalidate 是由函数声明定义的,它们是在代码的第一步运行之前创建的,因此它们在return 之后并不重要。

当您调用函数时(例如,调用 dataService 时),JavaScript 引擎会执行以下操作,并突出显示函数声明步骤:

  1. 设置this的值
  2. 为通话创建一个新环境(我们称之为env
  3. env 上设置对函数[[Scope]] 属性的引用(这是闭包工作原理的一部分)
  4. 为环境创建一个绑定对象(我们称之为bindings)来保存函数定义的各种名称(这是闭包如何工作的另一部分,也是变量引用如何已解决)
  5. 如果函数有名称,请将其作为引用函数的属性添加到bindings
  6. 将正式函数参数添加到bindings
  7. 处理函数声明,将它们的名称添加到bindings
  8. 创建arguments 对象,将其添加到bindings
  9. 将使用var 声明的每个变量添加到bindings(如果尚未定义),其值为undefined
  10. 在函数中处理逐步代码
  11. 设置调用表达式的结果

§10.4.1 中的规范及其链接的部分对此进行了详尽的阐述。 (如果你去读那篇文章,振作起来,散文是......笨重......)这是当前规范的链接,但这在 1999 年旧的第三版规范的第 10 节中也有明确规定,而且我很确定这从一开始就是正确的。

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

是的。它曾经让我感到紧张,所以几年前(可能是 2005 年左右)我在我能找到的所有当时流行且尚未死去的浏览器(包括 IE6)上向自己证明了这一点,并且普遍正确地处理了它。这实际上并不令人惊讶,因为它是使这段代码工作的原因:

doSomething();

function doSomething() {
    // ....
}

...人们一直这样做


这种“提升”是函数声明和函数表达式之间的主要区别之一。如果savevalidate 是由函数表达式 创建的,那么在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
        /* */
    };
}

savevalidate 变量将被创建(感谢上面的第 9 步),但就它们的使用位置而言,它们的值是 undefined,因此返回的对象不会没用。

【讨论】:

  • 哇,这对我来说是一个非常全面的答案和很多知识。现在接受它,并且……谢谢先生!
  • @bpiec:总是很高兴,我在几年前教过的 JavaScript 课程的一些材料中找到了列表,并且知道它在规范中的位置,所以......: -)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 2020-10-22
  • 2019-01-07
  • 2020-10-03
  • 1970-01-01
相关资源
最近更新 更多