Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
在 JavaScript 中,将变量定义为函数的目的是什么?我以前见过这个约定,但并不完全理解它。
例如,在脚本的某个时刻,一个函数被这样调用:
whatever();
但我希望看到一个名为 whatever
的函数,如下所示:
function whatever(){
}
相反,我会看到一个名为 whatever
的变量,它被定义为一个函数,如下所示:
var whatever = function(){
}
这样做的目的是什么?为什么要这样做而不只是命名函数?
注意:请参阅答案末尾的更新, block 内的声明变得有效(但如果您不使用严格模式,则相当复杂)。
这是一个原因:
var whatever;
if (some_condition) {
whatever = function() {
// Do something
};
}
else {
whatever = function() {
// Do something else
};
}
whatever();
您可能会在必须处理实现差异的库的初始化中看到类似的代码(例如 Web 浏览器之间的差异,a'la IE 的 attachEvent
与标准 addEventListener
)。你不能用函数声明做同样的事情:
if (some_condition) {
function whatever() { // <=== DON'T DO THIS
// Do something
}
}
else {
function whatever() { // <=== IT'S INVALID
// Do something else
}
}
whatever();
...它们没有在控制结构中指定,所以 JavaScript 引擎可以做他们想做的事,不同的引擎做不同的事情。 (编辑:再一次,请参阅下面的注释,它们现在已指定。)
分别来说,两者之间有很大的区别
var whatever = function() {
// ...
};
和
function whatever() {
// ...
}
第一个是函数表达式,当代码在逐步执行上下文(例如,它所在的函数,或逐步-逐步执行全局代码)。它还会生成一个匿名 函数(引用它的变量有一个名称,但函数没有,这对 helping your tools to help you 有影响)。
第二个是函数声明,它在进入上下文时进行评估,在执行任何分步代码之前。 (有些人称此为“提升”,因为源代码中更底层的事情比源代码中更高层的事情发生得更早。)该函数也被赋予了一个合适的名称。
所以考虑:
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "function"
function bar() {
}
}
鉴于
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "undefined"
var bar = function() {
};
}
在第一个示例中,通过声明,声明在doSomething
和其他分步代码运行之前 被处理。在第二个示例中,因为它是一个表达式,所以它作为逐步代码的一部分执行,因此函数没有在上面定义(变量在上面定义,因为 var
is also "hoisted" )。
最后:目前,您不能在一般的客户端 Web 内容中执行此操作:
var bar = function foo() { // <=== Don't do this in client-side code for now
// ...
};
您应该能够做到这一点,它被称为命名函数表达式,它是一个为函数赋予适当名称的函数表达式。但是不同时期的各种 JavaScript 引擎都出错了,IE continued to get very wrong indeed until very recently .
ES2015+更新
从 ES2015(又名“ES6”)开始, block 内的函数声明已添加到规范中。
严格模式
在严格模式下,新指定的行为简单易懂:它们被限制在它们出现的 block 内,并被提升到 block 的顶部。
所以这样:
"use strict";
if (Math.random() < 0.5) {
foo();
function foo() {
console.log("low");
}
} else {
foo();
function foo() {
console.log("high");
}
}
console.log(typeof foo); // undefined
(请注意对函数的调用是如何高于 block 中的函数的。)
...本质上等同于:
"use strict";
if (Math.random() < 0.5) {
let foo = function() {
console.log("low");
};
foo();
} else {
let foo = function() {
console.log("high");
};
foo();
}
console.log(typeof foo); // undefined
宽松模式
松散模式行为要复杂得多,而且理论上它在网络浏览器中的 JavaScript 引擎和网络浏览器中的 JavaScript 引擎之间有所不同。我不会在这里深入。只是不要这样做。如果您坚持在 block 内声明函数,请使用严格模式,因为它们有意义并且在整个环境中保持一致。