返回后定义函数

bpi*_*iec 8 javascript closures standards-compliance angularjs

我正在阅读John Papa的AngularJS风格指南,并看到了代码:

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

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

    function save() {
        /* */
    };

    function validate() {
        /* */
    };
}
Run Code Online (Sandbox Code Playgroud)

你可以看到,功能savevalidate定义的函数返回一个值.这是如何运作的?它是否符合标准并适用于所有浏览器(例如,来自IE 6)?

T.J*_*der 12

你可以看到,在功能savevalidate后的函数返回一个值的定义.

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

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

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

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

这在§10.4.1中的规范及其链接的部分中以极其详细的方式列出.(如果你去阅读那个,自我鼓励,散文就是......不稳定......)这是当前规范的一个链接,但这在1999年旧版第三版规范的§10中也有明确规定,而且我很确定从一开始就是如此.

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

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

doSomething();

function doSomething() {
    // ....
}
Run Code Online (Sandbox Code Playgroud)

......人们做所有的时间.


这种"提升"是函数声明和函数表达式之间的关键差异之一.如果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
        /* */
    };
}
Run Code Online (Sandbox Code Playgroud)

savevalidate变量会得到创建(由于在上述步骤9),但他们已经习惯的地方,他们就会有值undefined,因此返回的对象是没有用的.

  • 哇,这真是一个全面的答案,对我来说学到了很多知识。现在接受它,并且……谢谢先生! (3认同)