我目前正在阅读John Papa的AngularJS样式指南,并看到了以下代码:
function dataService() { var someValue = ''; var service = { save: save, someValue: someValue, validate: validate }; return service; //////////// function save() { /* */ }; function validate() { /* */ }; }
您可以看到函数save和validate是 在 函数返回值 之后 定义的。这是如何运作的?它是否符合标准并且可以在所有浏览器中使用(例如,来自IE 6)?
save
validate
您可以看到函数save和validate是在函数返回值之后定义的。
那是从它们的编写位置看的样子,是的,但是实际上它们是在函数中的任何分步代码完全运行之前定义的。有时这被称为“提升”函数顶部的声明(类似的情况var也发生在;下面还有更多)。
var
当控件进入执行上下文时(例如,当您输入函数,在程序开头输入全局环境或输入eval代码时), 在执行 任何分步代码 之前 发生的几件事之一是:处理该上下文中的所有函数 声明 ,并创建这些函数。由于save和validate是由函数声明定义的,因此它们是在代码的第一行逐步运行之前创建的,因此它们位于的后面也没关系return。
eval
return
在调用函数时(例如,在调用时dataService),其中突出显示了函数声明步骤,这是JavaScript引擎的工作:
dataService
this
env
[[Scope]]
bindings
arguments
undefined
在§10.4.1的规范及其链接的各节中,详细地列出了这一点。(如果您读懂了,大胆地做吧,散文是……笨拙的……)这是当前规范的链接,但这在1999年旧的第三版规范的§10中也有明确规定,我很确定从一开始就是对的。
它是否符合标准并且可以在所有浏览器中使用(例如,来自IE 6)?
是。它曾经使我感到紧张,所以几年前(大概是2005年),我在所有我能找到的当时流行且不死的浏览器(包括IE6)上向我证明了这一点,并且普遍正确地对其进行了处理。实际上这并不奇怪,因为这是使此代码起作用的原因:
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和validate变量会得到创建(由于在上述步骤9),但他们已经习惯的地方,他们就会有值undefined,因此返回的对象是没有用的。