为什么使用JavaScript函数声明(和表达式)?

为什么使用JavaScript函数声明(和表达式)?,javascript,Javascript,我见过其他人使用以下模式 var bar = function foo(){}; console.log(bar); // foo() console.log(foo); // ReferenceError: foo is not defined 但是为什么呢?如果两者都声明了,我可以理解这一点,但它们不是。原因是什么?调试应用程序时,当使用命名匿名函数时,更容易知道调用堆栈中调用的是什么。因此,这是一种为匿名函数命名以进行调试的方法 尝试此操作并查看调试器中的调用堆栈: myDiv = do

我见过其他人使用以下模式

var bar = function foo(){};
console.log(bar); // foo()
console.log(foo); // ReferenceError: foo is not defined

但是为什么呢?如果两者都声明了,我可以理解这一点,但它们不是。原因是什么?

调试应用程序时,当使用命名匿名函数时,更容易知道调用堆栈中调用的是什么。因此,这是一种为匿名函数命名以进行调试的方法

尝试此操作并查看调试器中的调用堆栈:

myDiv = document.getElementById("myDiv");

myDiv.onclick = function OnClick(){
    debugger;
    //do something
}

他们命名一个匿名函数,因为它使调试更容易。调试时,您将在调用堆栈中看到对foo的调用,而不是对anonymous的一系列调用。

我能想到的唯一原因是为函数指定所需的名称。这有助于调试,因为检查器使用函数对象的name属性。试试这个:

var bar = function foo(){};
console.log(bar.name); // foo

如果在foo中放入一些真实代码,并在浏览器中的JavaScript调试器中添加断点,您将在调用堆栈中看到函数作为foo。

如其他人所述,使用示例中的第一种形式命名函数表达式可以帮助调试,尽管最近浏览器内置开发工具有所改进,但这一观点的说服力正在减弱。使用命名函数表达式的另一个原因是,可以将函数名用作函数体中的变量,而不是ES5 arguments.callee中现在已弃用的变量


但是,在Internet Explorer<9中,命名函数表达式的实现不正确且存在问题,当您针对这些浏览器时,通常应避免使用。有关更多信息,请参阅。

函数定义或文字包含4个部分。1.保留字功能2。可供调试器或函数递归调用自身的可选名称。3.参数和4。由{}包装的函数体

函数范围之外的foo不存在。但是,由于您将函数分配给变量栏,所以可以使用方法调用栏调用它,并且由于定义了变量栏,所以可以打印它


如果你对JavaScript感兴趣,你应该考虑得到

你所得到的是一个匿名函数,它有一个名字。我知道这样做的唯一原因是,当您调试到foo函数时,堆栈跟踪将显示名称,而不仅仅是“匿名函数”。+1用于在内部作用域中提及函数名称的可见性。+1,如Mozilla的官方文档所示,函数名称只能在函数体中使用。注意在IE<9中使用命名函数表达式:这些浏览器中的实现已被破坏。更详细地说,在早期版本的ie中,函数对onclick属性的赋值是不正确的,而不是语法函数onclick{}。@Zoidberg:不,我不是这个意思。语法var foo=函数栏{};它本身肯定在IE<9中被破坏。另外,DOM0事件处理程序属性,例如myDiv.onclick=function{};在IE中工作得很好。我想你正在考虑设置属性,例如myDiv.setAttributeonclick,警报“click”;,这在旧的IE中被打破了。我在IE 8和更少的版本中使用了函数{},它对我来说很好。它没有编译,请详细说明什么是坏的。@Zoidberg:详细内容都在我链接的文章中。虽然它通常会工作,但它的问题很微妙,这意味着它可能导致难以发现的bug。