只是出于兴趣,两者之间是否存在任何速度/功能差异
function foo(bar) {
alert("foo" + bar);
}
和
var foo = function(bar) {
alert("foo" + bar);
};
只是出于兴趣,两者之间是否存在任何速度/功能差异
function foo(bar) {
alert("foo" + bar);
}
和
var foo = function(bar) {
alert("foo" + bar);
};
没有显着的速度差异。(测试)
存在功能差异。
如果您四处寻找“函数声明”与“函数表达式”,您会发现很多关于该主题的讨论(其中一些甚至是正确的)。
但简而言之:
当执行游标进入其包含范围(包含函数或全局范围)时,会在执行任何分步代码之前发生像您的第一个示例一样的函数声明。因此它们不能出现在非功能块(if
、try
等)中,因为在处理它们时没有运行分步代码。函数的名称被添加到它出现的范围内,并且函数对象有一个真实的名称(尽管没有标准的方法来查询该名称,但它在堆栈跟踪等中仍然有用)。(注意:一些 JavaScript 引擎允许在块内声明函数,但这是无效的,它们所做的不一定一致。不要这样做。)
像您的第二个示例这样的函数表达式与所有表达式一样,在代码的逐步流程中遇到时会发生。您的表达式称为匿名函数表达式,因为它没有明确指定函数的名称。在 ES5 及更早版本中,这意味着生成的函数没有名称。在 ES6/ES2015 及更高版本中,许多使用匿名函数表达式创建的函数确实具有名称,因为可以从表达式中推断出名称,而您的示例就是这种情况,其中函数以变量具有的名称结束:foo
. 由于匿名函数表达式是表达式,它们可以出现在任何可能出现表达式的地方,尽管有时您必须警告解析器您正在执行此操作。
还有第三种方法:命名函数表达式,而不是匿名函数表达式。它们看起来像这样:
var foo = function bar() {
};
或者
var obj = {
foo: function bar() {
}
};
或者
doSomething(function bar() { });
等等
它们曾经是真正有问题的跨浏览器(例如,IE8 和更早的版本把它们弄乱了;Safari 的早期版本有问题,等等;Kangax 有一个很好的页面来说明过去比比皆是的问题)。它是一个表达式,所以它在任何有表达式的地方都有效。兼容的 JavaScript 引擎不会将函数名称(bar
在我的示例中)添加到包含范围。