AFAIK函数foo( ){aaa(); }在JavaScript中只是var foo = function(){aaa()}。
这实际上是不正确的。 JavaScript有两个不同但相关的东西:函数声明和函数表达式。它们在解析周期的不同时间发生并具有不同的效果。
这是一个功能声明:
function foo() {
// ...
}
函数声明在进入封闭的范围进行处理,在执行任何步骤一步代码之前。
这是一个功能表达(具体地,一个匿名一个):
var foo = function() {
// ...
};
函数表达式被处理为一步一步的代码的一部分,在该点处,其中它们出现(如同任何其他表达)。
你引用的代码是使用命名的函数表达式,它看起来像这样:
var x = function foo() {
// ...
};
(在你的情况下,它是一个对象中文字,所以它的上:
的右侧,而不是=
,但它仍然是一个命名的函数表达式。)
这是完全有效的,忽略了实现错误(稍后)。它创建一个名称为foo
,而不是将foo
放在封闭范围内的函数,然后将该函数分配给x
变量(在逐步代码中遇到表达式时发生的所有这些)。当我说不会把foo
在封闭的范围,我的意思正是:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
注意如何那是从单向函数不同声明工作(其中函数名是加入到封闭范围)。
命名函数表达式适用于兼容实现。从历史上看,实施中存在一些错误(早期的Safari,IE8和更早的版本)。现代实现让他们正确,包括IE9以上。 (更多在这里:Double take这里:Named function expressions demystified)
所以,在这个例子中me
变量shoudl不corectly从方法
其实里面解决的,也是应该的。函数的真实名称(function
与左括号之间的符号)始终在函数内(无论函数来自声明还是命名函数表达式)。
注意:下面是在2011年写的。随着JavaScript的进步,我不再需要做下面的事情,除非我知道我将要处理IE8(这是非常这些天罕见)。
由于执行错误的,我用来避免命名的函数表达式。你可以做你的榜样仅通过去除me
名称,但I prefer named functions,因此对于它的价值,这里就是我以前写你的对象:
var foo = (function(){
var publicSymbols = {};
publicSymbols.bar1 = bar1_me;
function bar1_me() {
var index = 1;
alert(bar1_me);
}
publicSymbols.bar2 = bar2_me;
function bar2_me() {
var index = 2;
alert(bar2_me);
}
return publicSymbols;
})();
(除了我可能会使用一个较短的名称比publicSymbols
)
下面是该得到处理:
- 当在一步一步的代码中遇到
var foo = ...
行会创建一个匿名的封闭功能,然后它被称为(因为我有Ť他在最后)()
。
- 一旦进入由匿名函数创建的执行上下文,则
bar1_me
和bar2_me
函数声明被处理并且这些符号被添加到匿名函数内的范围(在技术上,与可变对象用于执行上下文)。
publicSymbols
符号被添加到匿名函数的范围内。 (更多:Poor misunderstood var
)
- 分步代码首先将
{}
指定为publicSymbols
。
- 步骤一步码连续用
publicSymbols.bar1 = bar1_me;
和publicSymbols.bar2 = bar2_me;
,最后return publicSymbols;
- 匿名函数的结果被分配给
foo
。
这些天来,虽然,除非我在写代码,我知道需要支持IE8(可悲的是,我写这篇文章在2015年11月它还是有significant global market share,但令人高兴的是份额plummetting),我不知道担心它。所有现代JavaScript引擎都很好理解它们。
你也可以写这样的:
var foo = (function(){
return {
bar1: bar1_me,
bar2: bar2_me
};
function bar1_me() {
var index = 1;
alert(bar1_me);
}
function bar2_me() {
var index = 2;
alert(bar2_me);
}
})();
...因为这些是函数的声明,并因此被悬挂。我通常不这样做,因为我发现如果我在声明和属性之间进行分配(或者,如果不是为IE8编写的话,在同一行中),则更容易对大型结构进行维护。 。
我读过你的问题3次,我仍然无法理解你的问题 – Luis
@Luis:这是创建和范围是什么,他们有函数名何时以及如何对一个玄之又玄的问题。是的,追踪有点棘手。 :-) –
对不起,如果问题出在我的英语,我不是一个母语。 – tillda