//DON'T DO THIS!
if (x) {
function foo() { return 1; }
} else {
function foo() { return 2; }
}
foo(); //will always be 2, regardless of the value of x.
函数表达式略有不同 . 通常,它们直接分配给变量,如下所示:
var foo = function() { /* ... */ };
这与上面的函数声明几乎完全相同,只是不提升初始化 . 所以你可以做到以下几点:
var foo;
if (x) {
foo = function() { return 1; };
} else {
foo = function() { return 2; };
}
foo(); //will be 1 or 2, depending on the truthy-ness of x.
3 回答
在JavaScript中创建函数有两种方法,一种是“函数声明”和一种“函数表达式” . 我相信Doug Crockford最好解释说,除非“function”是给定行上的第一组字符,否则你执行的是函数表达式(不是声明) .
函数声明是挑剔的生物 . 当你看到它们时,你会认出它们 . 它们看起来像这样:
它们总是被赋予一个名称(它是必需的),并且名称是本地作用于声明函数的词汇上下文 . 因此,如果在全局上下文中执行函数声明,则可以通过全局名称引用该函数 . 如果在函数内执行,则只能在该函数和该函数中声明的任何函数中引用函数的名称 .
我认为这种声明一个函数的方法(一个很少被评论的方法)最重要的方面是函数初始化被提升到当前词汇上下文的顶部 . 因此,您永远不应该在条件中使用函数声明,例如:
函数表达式略有不同 . 通常,它们直接分配给变量,如下所示:
这与上面的函数声明几乎完全相同,只是不提升初始化 . 所以你可以做到以下几点:
所以,回到最初的问题 . 函数表达式也可以有一个名称,虽然它不是必需的,并且它没有作用于声明函数的上下文(与函数声明一样) . 相反,它将范围限定在函数自己的词汇上下文中 . 这在某些情况下非常有用 . 我个人最喜欢的是这种模式:
由于"function"之前的括号,这是一个函数表达式,名称仅在内部作用域 . 但那没关系,因为我们只需要在内部调用它(通过
setTimeout()
) . 结果是函数将立即执行一次,然后在完成执行后每秒左右重新执行一次 . 这比使用setInterval()
更安全,因为它会等到重新安排自己之前完成执行,从而防止可能导致错过执行的重叠和/或JavaScript线程的"domination" .从本质上讲,命名函数表达式的使用是有限的,但是当你需要它时,它非常强大 .
用于调用自身的功能 .
你指的是一个命名函数表达式 . 规范要求此类函数的名称仅在新函数的范围内可用 . Spec quote:
另一方面,该表达式的结果是对新函数的引用,可以在任何地方保存和引用它 .
这里有很多细节:
我读了整篇文章 .
至于好处,另一个是它使它们更容易在调试器中识别 .