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

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

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

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=function bar(){}本身在IE<9中肯定被破坏了。此外,DOM0事件处理程序属性(例如
myDiv.onclick=function(){};
)在IE中也可以正常工作。我想您可能正在考虑
setAttribute()
(例如
myDiv.setAttribute(“onclick”,“alert('click')”);
),它在旧的IE中被打破了。我在IE8及更低版本中使用过function(){},对我来说也可以正常工作。它不是编译的,请详细说明什么是坏的。@Zoidberg:详细信息都在我链接的文章()中。虽然它通常会工作,但它的问题很微妙,这意味着它可能导致难以发现的bug。