在JavaScript中,命名函数比匿名函数更受欢迎吗?

在JavaScript中,命名函数比匿名函数更受欢迎吗?,javascript,Javascript,可能重复: 在Javascript中提取函数有两种可能的方法: var foo = function() { ... } 这有点做作;另一种常见模式是: var foo = { baz: 43, doSomething: function() { // ... } } 对 function foo() { // ... } 是否有明确的理由选择其中一个呢?归根结底,这取决于您对函数声明位置的偏好;起重 JavaScript解释器总是将函数声明和变量

可能重复:

在Javascript中提取函数有两种可能的方法:

var foo = function() { ... }
这有点做作;另一种常见模式是:

var foo = {
   baz: 43,
   doSomething: function() {
       // ...
   }
}

function foo() { 
  // ... 
}

是否有明确的理由选择其中一个呢?

归根结底,这取决于您对函数声明位置的偏好;起重

JavaScript解释器总是将函数声明和变量声明以不可见的方式移动(“提升”)到其包含范围的顶部。显然,函数参数和语言定义的名称已经存在。这意味着像这样的代码:

function foo() {
    bar();
    var x = 1;
}
function foo() {
    var x;
    bar();
    x = 1;
}
{ name1: val1, .... namek:valk }
实际上是这样理解的:

function foo() {
    bar();
    var x = 1;
}
function foo() {
    var x;
    bar();
    x = 1;
}
{ name1: val1, .... namek:valk }
请注意,声明的转让部分未被悬挂。只有名字被悬挂。函数声明的情况并非如此,整个函数体也将被提升

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();
在这种情况下,只有函数声明的主体被提升到顶部。名称“foo”已被提升,但主体被留下,在执行过程中分配

您可以使用类似于函数声明的语法为函数表达式中定义的函数命名。这并不意味着它是一个函数声明,名称也没有被纳入范围,主体也没有被提升

foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
bin(); // ReferenceError "bin is not defined"

var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted)

foo(); // valid
bar(); // valid
baz(); // valid
bin(); // ReferenceError "bin is not defined"
因此,如果您希望让函数升到顶部,请使用
函数声明
,否则请使用
表达式
。我更喜欢后者,因为我通常使用
函数表达式
等方法构建对象文本


当抛出错误时,命名的
函数表达式
非常方便。控制台将告诉您函数是什么,而不是声明
匿名
aka堆栈跟踪

命名函数没有什么好处

  • 元分析的名称
    functionInstance.name
    将显示名称
  • 更重要的是,名称将打印在堆栈跟踪中
  • 名称也有助于编写自文档或可读代码
命名函数表达式有一个缺点

  • IE有NFE的内存泄漏

函数声明没有缺点,只是风格控制较少

你的问题实际上由两部分组成,因为如果函数被分配给变量或属性,你不一定要使函数匿名

匿名与匿名?

@雷诺斯清晰地突出了要点。命名函数最好的部分是它们将在堆栈跟踪中显示自己。即使在函数被分配给变量/属性的情况下,给函数起一个名字是一个好主意,只是为了帮助调试,但是我不会说匿名函数是邪恶的。它们确实有很好的用途:

函数声明与函数表达式?

对于问题的这一部分,我会让你们参考这个问题,因为它可能比我能做的更深入地涵盖了这个主题


你在这里碰到了两件不同的事情,但我将尝试先回答你的主要问题

总的来说

function(){…}
是一个函数表达式。从语法上讲,这与
2
[4,5]
处于同一级别。这表示一个值。因此,每次执行
var foo=function(){…}
都将按计划工作

函数foo(){…}
是一个函数声明。这似乎与
var foo=function(){…}
的作用相同,但有一点需要注意。作为一种声明,它的工作原理类似于JS中变量提升的概念(基本上,所有变量声明都是在计算任何表达式之前完成的)

一个很好的例子是:

基本上,可变起重将该值提高到最高值,因此该代码(理论上)等同于:


注:我想借此机会说,JS口译员很难遵循理论,因此不建议在有些不确定的行为上信任他们。在一节的末尾,你会发现一个很好的例子,理论和实践最终都不起作用(还有一些关于表达式和声明主题的更多细节)

有趣的事实:将
函数foo(){…}
包装在括号中,将其从声明转换为表达式,这可能会导致一些奇怪的代码,如

(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined
如果你没有理由,请不要这样做


Summary
var foo=function(){…}
与function
foo(){…}
有点类似,只是前者做你认为它应该做的事情,而后者做奇怪的事情,除非你把它包装成paren,但这会弄乱范围,JS解释器允许你做一些在规范中被认为是语法错误的事情,这样你就会相信错误的事情实际上是正确的,等等

请使用函数表达式(
var f=function(){…}
)。没有真正的理由不这样做,特别是考虑到当您使用点语法时,您有点被迫这样做


关于你碰过的第二件事

我真的不知道该说什么,这有点完全不同于关于这件事的一切

var foo = {
    baz: 43,
    doSomething:function() {
        ...
    }
}
这称为对象文字语法。基于这种语法的JSON是,JS中的这种语法通常用于声明新对象,例如单例对象(避免声明函数和使用新对象的混乱)。它也可以像使用XML一样使用,并且是所有酷孩子的首选

无论如何,基本上对象文字语法是这样工作的:

function foo() {
    bar();
    var x = 1;
}
function foo() {
    var x;
    bar();
    x = 1;
}
{ name1: val1, .... namek:valk }
此表达式是一个初始化了某些值的对象。这样做
var obj={name1:val1,….namek:valk}
意味着:

obj.name1==val1;
obj['name1']==val1;// x['y'] is the same thing as x.y 
...
obj.namek==valk;