草庐IT

javascript - 返回后定义函数

coder 2024-07-18 原文

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

最佳答案

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

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

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

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

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

这在 §10.4.1 的规范中有极其详细的说明以及它链接到的部分。 (如果你去读它,打起精神来,散文是......浮夸......)这是当前规范的链接,但这在 1999 年的旧第三版规范的第 10 节中也有明确规定,我相当确定这从一开始就是正确的。

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

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

doSomething();

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

...人们一直都是这样做的


这种“提升”是函数声明 和函数表达式 之间的主要区别之一。如果savevalidate由函数 expressions 创建,那么它们写在 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因此返回的对象将没有用。

关于javascript - 返回后定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26927617/

有关javascript - 返回后定义函数的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

随机推荐