可能重复:
JavaScript: var functionName = function() {} vs function functionName() {}
在JavaScript中,将变量定义为函数的目的是什么?我以前见过这个惯例,并没有完全理解它。
例如,在脚本中的某个时刻,会调用一个函数:
whatever();
但是我期望看到一个名为whatever
的函数,就像这样:
function whatever(){
}
相反,我会看到一个名为whatever
的变量,它被定义为一个函数,如下所示:
var whatever = function(){
}
这是为了什么目的?你为什么要这样做而不只是命名函数?
答案 0 :(得分:34)
注意:请参阅答案末尾的更新,块内的声明变得有效(但如果您没有使用严格模式,则相当复杂)。
这是一个原因:
var whatever;
if (some_condition) {
whatever = function() {
// Do something
};
}
else {
whatever = function() {
// Do something else
};
}
whatever();
您可能会在库的初始化中看到类似的代码,这些代码必须处理实现差异(例如Web浏览器之间的差异,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")
结束:目前,你不能在一般的客户端网站上做到这一点:
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(又名“ES6”)开始,块中的函数声明被添加到规范中。
在严格模式下,新指定的行为简单易懂:它们的范围限定在它们出现的块中,并被提升到它的顶部。
所以这个:
"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
(注意对函数的调用是上面块中的函数。)
...基本上等同于:
"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
松散模式行为要复杂得多,而且理论上它在Web浏览器中的JavaScript引擎和Web浏览器中的 之间的JavaScript引擎之间有所不同。我不会在这里介绍它。只是不要这样做。如果你坚持使用块中的函数声明,那么使用严格模式,它们是有意义的,并且在不同的环境中是一致的。
答案 1 :(得分:2)
这样你就可以将函数存储在变量中,例如将它们作为参数传递给其他函数。这有用的一个例子是编写异步函数,它们将回调作为参数传递给
var callback = function() { console.log('done', result)}
var dosomething = function(callback) {
//do some stuff here
...
result = 1;
callback(result);
}
由于函数是javascript中的对象,因此您也可以使用属性和方法扩展它们。
答案 2 :(得分:1)
将函数赋值给变量时,可以将其作为参数传递给其他函数,并将其扩展为使用Javascript的对象模型。
答案 3 :(得分:0)
JavaScript中的函数是对象;换句话说,他们是值。因此,无论函数如何定义,您都可以始终设置变量以引用函数:
function foo() { ... }
var anotherFoo = foo;
anotherFoo(); // calls foo
函数是可以用作对象属性,函数参数,数组元素以及一般值可以在JavaScript中执行的任何其他操作的值。它们是对象,也可以拥有自己的属性。
答案 4 :(得分:0)
如果在函数内使用“var”声明函数变量,则只能在该函数中访问变量 。退出该函数时,该变量将被销毁。这些变量称为局部变量。您可以在不同的函数中使用相同名称的局部变量,因为每个函数只能被声明它的函数识别。