25

只是出于兴趣,两者之间是否存在任何速度/功能差异

function foo(bar) {
    alert("foo" + bar);
}

var foo = function(bar) {
    alert("foo" + bar);
};
4

1 回答 1

27

没有显着的速度差异。(测试

存在功能差异。

  • 函数声明(如您的第一个)和函数表达式(如您的第二个)在不同时间处理。
  • 它们对它们发生的范围有不同的影响。
  • 你的第一个函数有一个真实的名字你的第二个在 ES5 和更早的版本中没有,你的第二个没有;在 ES6/ES2015 中确实如此,因为规范说 JavaScript 引擎在这种情况下必须将变量的名称分配给函数。

如果您四处寻找“函数声明”与“函数表达式”,您会发现很多关于该主题的讨论(其中一些甚至是正确的)。

但简而言之:

函数声明

当执行游标进入其包含范围(包含函数或全局范围)时,会在执行任何分步代码之前发生像您的第一个示例一样的函数声明。因此它们不能出现在非功能块(iftry等)中,因为在处理它们时没有运行分步代码。函数的名称被添加到它出现的范围内,并且函数对象有一个真实的名称(尽管没有标准的方法来查询该名称,但它在堆栈跟踪等中仍然有用)。(注意:一些 JavaScript 引擎允许在块内声明函数,但这是无效的,它们所做的不一定一致。不要这样做。)

匿名函数表达式

像您的第二个示例这样的函数表达式与所有表达式一样,在代码的逐步流程中遇到时会发生。您的表达式称为匿名函数表达式,因为它没有明确指定函数的名称。在 ES5 及更早版本中,这意味着生成的函数没有名称。在 ES6/ES2015 及更高版本中,许多使用匿名函数表达式创建的函数确实具有名称,因为可以从表达式中推断出名称,而您的示例就是这种情况,其中函数以变量具有的名称结束:foo. 由于匿名函数表达式是表达式,它们可以出现在任何可能出现表达式的地方,尽管有时您必须警告解析器您正在执行此操作。

命名函数表达式

还有第三种方法:命名函数表达式,而不是匿名函数表达式。它们看起来像这样:

var foo = function bar() {
};

或者

var obj = {
    foo: function bar() {
    }
};

或者

doSomething(function bar() { });

等等

它们曾经是真正有问题的跨浏览器(例如,IE8 和更早的版本把它们弄乱了;Safari 的早期版本有问题,等等;Kangax 有一个很好的页面来说明过去比比皆是的问题)。它是一个表达式,所以它在任何有表达式的地方都有效。兼容的 JavaScript 引擎不会函数名称bar在我的示例中)添加到包含范围。

于 2012-11-10T15:15:34.087 回答