Two functions with the same name in JavaScript - how can this work?
据我所知,
因此,在本例中,不应该从方法内部正确地解析
1 2 3 4 5 6 7 8 9 10 11 12 13 | var foo = { bar1 : function me() { var index = 1; alert(me); }, bar2 : function me() { var index = 2; alert(me); } }; foo.bar1(); // Shows the first one foo.bar2(); // Shows the second one |
演示:http://jsfiddle.net/w5dqy/5/
AFAIK function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript.
这实际上是错误的。JavaScript有两个不同但相关的东西:函数声明和函数表达式。它们在解析周期中的不同时间发生,并且具有不同的效果。
这是一个函数声明:
1 2 3 | function foo() { // ... } |
函数声明在进入封闭范围时进行处理,然后再执行任何分步代码。
这是一个函数表达式(特别是匿名表达式):
1 2 3 | var foo = function() { // ... }; |
函数表达式被作为逐步代码的一部分处理,在它们出现的地方(就像任何其他表达式一样)。
引用的代码使用的是一个命名函数表达式,如下所示:
1 2 3 | var x = function foo() { // ... }; |
(在您的例子中,它在对象文本中,所以它位于
这是完全有效的,忽略了实现错误(稍后会更多)。它创建一个名为
1 2 3 4 | 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和here:已命名的函数表达式已解除定义。)
So, in this example the
me variable shoudl not be corectly resolved from inside the methods
事实上,应该是。函数的真名称(
注:以下为2011年编写。随着Javascript的发展,我不再觉得有必要做下面这样的事情,除非我知道我将要处理IE8(这在现在是非常罕见的)。
由于实现错误,我常常避免使用命名函数表达式。在您的示例中,您只需删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; })(); |
(除了我可能会用一个比
这是如何处理的:
不过,现在,除非我正在编写代码,否则我知道需要支持IE8(遗憾的是,正如我在2015年11月写的那样,它仍然拥有巨大的全球市场份额,但令人高兴的是,它的份额正在下降),我不担心它。所有现代的javascript引擎都能很好地理解它们。
你也可以这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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写,在同一行),就更容易对大型结构进行维护。
两个
事实上,这两个表达式都是命名函数表达式,而ecmascript规范告诉我们,表达式的名称不会暴露于所谓的
好吧,我试着只用几句话来表达,但是当我试图找到合适的词语时,这最终导致了一系列令人欣喜若狂的行为。因此,
短:每次调用函数时,都会创建一个新的
- 函数的参数
- [ [范围] ]
- 由
var 创建的任何变量
例如:
1 2 3 4 5 6 7 8 9 | function foo(test, bar) { var hello ="world"; function visible() { } (function ghost() { }()); } |
- 参数:测试,bar
- 变量:hello(字符串),visible(函数)
- [[scope]]:(可能的父函数上下文),全局对象
这里所发生的是,
当我说
1 2 | bar1 : function me() { } |
那么100%相当于
1 2 | bar1 : function() { } |
也就是说,当使用函数分配变量