我目前正在阅读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() {
/* */
};
}
您可以看到函数save
和validate
在函数返回值后定义为。这是如何运作的?它是否符合标准并适用于所有浏览器(例如,来自IE 6)?
答案 0 :(得分:11)
您可以看到函数
save
和validate
是在函数返回值后定义的。
这就是从它们写入的位置看起来的样子,是的,但实际上它们是在函数中的任何分步代码运行之前定义的。有时这被称为“将”声明“提升”到函数的顶部(类似的情况也发生在var
;更多信息发生在下面)。
当控制进入执行上下文时(例如,当您输入一个函数时,在程序开头输入全局环境,或输入eval
代码),这是之前发生的几个事情之一 执行的任何分步代码都是处理该上下文中的所有函数声明并创建这些函数。由于save
和validate
是由函数声明定义的,因此它们是在代码的第一个逐步行之前创建的,因此它们在{ {1}}。
以下是调用函数时JavaScript引擎的作用(例如,调用return
时),突出显示函数声明步骤:
dataService
this
)env
上设置对函数[[Scope]]
属性的引用(这是闭包工作方式的一部分)env
)来保存我们由函数定义的各种名称(这是闭包如何工作的另一部分,以及如何变量引用已解决)bindings
bindings
bindings
bindings
对象,将其添加到arguments
bindings
声明的每个变量添加到var
(如果尚未定义),其值为bindings
这在§10.4.1及其链接的部分中的规范中列出了极其详细的内容。 (如果你去阅读那个,自我鼓励,散文就是......不稳定......)这是当前规范的一个链接,但这在1999年旧版第三版规范的§10中也有明确规定,而且我很确定从一开始就是真的。
它是否符合标准并适用于所有浏览器(例如,来自IE 6)?
是。它曾经让我感到紧张,所以几年前(可能〜2005年)我在我能找到的所有当时和非常死的浏览器(包括IE6)上证明了这一点,并且它得到了普遍正确的处理。这实际上并不令人惊讶,因为这是使这段代码有效的原因:
undefined
......人们一直这样做。
这种“提升”是函数声明和函数表达式之间的关键区别之一。如果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
个变量(感谢上面的步骤9),但是在使用它们的地方,它们的值为validate
并且所以返回的对象没用。