返回后定义函数 [英] Defining functions after return

查看:21
本文介绍了返回后定义函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently reading John Papa's AngularJS style guide and saw the code:

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

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

    function save() {
        /* */
    };

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

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

You can see that the functions save and validate are defined after the function returned a value. How does this work? Is it standard-compliant and works in all browsers (say, from IE 6)?

推荐答案

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

You can see that the functions save and validate are defined after the function returned a value.

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

That's what it looks like from where they're written, yes, but in fact they're defined before any step-by-step code in the function runs at all. Sometimes this is called "hoisting" the declarations to the top of the function (something similar happens with var, too; more below).

当控制进入一个执行上下文时(例如,当你进入一个函数,进入程序开始时的全局环境,或者进入eval代码),发生的几种事情之一在执行任何分步代码之前是处理该上下文中的所有函数声明并创建这些函数.由于 savevalidate 是由函数声明定义的,因此它们是在代码的第一行逐步运行之前创建的,因此无关紧要他们在 return 之后.

When control enters an execution context (e.g., when you enter a function, enter the global environment at the beginning of the program, or enter eval code), one of the several things that happens before any step-by-step code is executed is that all of the function declarations in that context are processed and those functions are created. Since save and validate are defined by function declarations, they're created before the first step-by-step line of the code runs, and so it doesn't matter that they're after the return.

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

Here's what the JavaScript engine does when you call a function (e.g., when calling dataService), with the function declarations step highlighted:

  1. 设置this
  2. 的值
  3. 为调用创建一个新环境(我们称之为env)
  4. env 上设置对函数的 [[Scope]] 属性的引用(这是闭包工作原理的一部分)
  5. 为环境创建一个绑定对象(我们称之为bindings)来保存我们由函数定义的各种名称(这是闭包工作的另一部分,以及如何解析变量引用)
  6. 如果函数有名称,则将其添加到 bindings 作为引用函数的属性
  7. 将形式函数参数添加到 bindings
  8. 处理函数声明,将它们的名称添加到bindings
  9. 创建arguments 对象,将其添加到bindings
  10. 将用 var 声明的每个变量添加到 bindings(如果尚未定义),其值为 undefined
  11. 处理函数中的逐步代码
  12. 设置调用表达式的结果
  1. Set the value of this
  2. Create a new environment (let's call it env) for the call
  3. Set up a reference to the function’s [[Scope]] property on env (this is part of how closures work)
  4. Create a binding object (let's call it bindings) for the environment to hold our the various names defined by the function (this is another part of how closures work, and also how variable references are resolved)
  5. If the function has a name, add it to bindings as a property referring to the function
  6. Add the formal function arguments to bindings
  7. Process function declarations, adding their names to bindings
  8. Create the arguments object, add it to bindings
  9. Add each variable declared with var to bindings (if not already defined) with the value undefined
  10. Process the stepwise code in the function
  11. Set the call expression’s result

的规范中详细阐述了这一点§10.4.1 及其链接的部分.(如果你去阅读它,振作起来,散文是... turgid...)这是当前规范的链接,但这也明确规定在 1999 年旧的第三版规范的第 10 节中,而且我很确定它从一开始就是正确的.

This is laid out in excruciating detail in the spec in §10.4.1 and the sections it links to. (If you go to read that, brace yourself, the prose is...turgid...) That's a link to the current spec, but this was clearly laid out in §10 of the old third edition spec in 1999 as well, and I'm fairly sure it's been true right from the beginning.

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

Is it standard-compliant and works in all browsers (say, from IE 6)?

是的.它曾经让我感到紧张,所以几年前(大概是 2005 年)我在我能找到的所有当时流行的和还没有完全消亡的浏览器(包括 IE6)上向自己证明了这一点,并且它得到了普遍的正确处理.这实际上并不令人惊讶,因为它是使这段代码工作的原因:

Yes. It used to make me nervous, so several years back (probably ~2005) I proved it to myself on all of the then-current and not-quite-dead browsers I could find (including IE6), and it was universally handled correctly. Which isn't actually surprising, because it's what makes this code work:

doSomething();

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

...人们一直这样做.

这种提升"是函数声明和函数表达式之间的主要区别之一.如果savevalidate是由函数表达式创建的,那么在return之后编写它们就很重要了代码> —它们根本不会被创建:

This "hoisting" is one of the key differences between function declarations and function expressions. If save and validate were created by function expressions, then it would matter a great deal that they were written after the return — they'd never get created at all:

// 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 所以返回的对象没有用处.

The save and validate variables would get created (thanks to Step 9 in the above), but as of where they're used, they'd have the value undefined and so the returned object wouldn't be useful.

这篇关于返回后定义函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆