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

Are named functions preferred over anonymous functions in JavaScript?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}

在javascript中,有两种可能的方法来提取函数:

1
var foo = function() { ... }

这有点做作;另一个常见的模式是:

1
2
3
4
5
6
var foo = {
   baz: 43,
   doSomething: function() {
       // ...
   }
}

对战

1
2
3
function foo() {
  // ...
}

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


所有这些都取决于你在哪里声明你的功能;提升。

函数声明和变量声明总是被javascript解释器无形地移动("提升")到其包含范围的顶部。显然,函数参数和语言定义的名称已经存在。这意味着这样的代码:

1
2
3
4
function foo() {
    bar();
    var x = 1;
}

实际解释如下:

1
2
3
4
5
function foo() {
    var x;
    bar();
    x = 1;
}

注意声明的分配部分没有被提升。只有名字被提升。这与函数声明不同,整个函数体也将被提升。

1
2
3
4
5
6
7
8
9
10
11
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"这个名字被提升了,但是尸体被留在后面,在执行过程中被分配。

您可以为函数表达式中定义的函数命名,语法类似于函数声明。这不会使其成为函数声明,也不会将名称纳入范围,也不会提升主体。

1
2
3
4
5
6
7
8
9
10
11
12
13
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"

因此,如果您的偏好是让功能提升到顶部,则使用function declaration,否则使用expression。我更喜欢后者,因为我通常使用function expressions方法构建对象文本。

当抛出错误时,名为function expressions的方法非常方便。控制台将告诉您函数是什么,而不是说明anonymousaka堆栈跟踪。


你在这里碰到了几个不同的问题,但我会先回答你的主要问题。

一般来说。。。。

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

function foo() { ... }是一个函数声明。这似乎和var foo=function(){...}的做法一样,但也有一个小小的警告。作为声明,它的工作原理类似于JS中变量提升的概念(基本上,所有变量声明都是在计算任何表达式之前完成的)。

这里有一个很好的例子:

1
2
3
4
5
6
7
8
9
10
11
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();

基本上,可变起重已经将该值提升到顶部,因此该代码(理论上)相当于:

1
2
3
4
5
6
7
8
9
10
11
12
function test() {
    var foo;//foo hoisted to top
    var bar=function(){//this as well
        alert("this will run!");
    }

    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!");
    }
}

注意:我想借此机会说,JS解释器很难遵循理论,因此不建议将它们信任于有些不确定的行为。在这里,您将在一节的末尾找到一个很好的例子,理论和实践最终都不起作用(还有一些关于表达式与声明主题的更多细节)。

有趣的事实:将function foo() {...}括在括号中可以将其从声明转换为表达式,这可能导致一些奇怪的代码

1
2
(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined

如果你没有理由,请不要这样做。

摘要var foo=function(){ ... }与函数foo(){ ... }大致相同,只是前者在您认为应该的地方做您认为应该做的事情,而后者做一些奇怪的事情,除非您用parens包装它,但这会破坏作用域,而js解释器允许您做规范中认为语法错误的事情,因此您可以我相信错误的事情事实上是正确的,等等。

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

在你接触到的第二件事上……

我真的不知道该说什么,这有点完全不同于其他一切。

1
2
3
4
5
6
var foo = {
    baz: 43,
    doSomething:function() {
        ...
    }
}

这被称为对象文本语法。基于这种语法的JSON是格式化数据的一种非常好的方法,而JS中的这种语法通常用于声明新对象,例如,使用singleton对象(避免在声明函数和使用new时出现所有混乱)。它也可以用同样的方式使用XML,并且是所有酷孩子的首选…

总之,基本上,对象文本语法的工作方式如下:

1
{ name1: val1, .... namek:valk }

此表达式是一个对象,其上初始化了某些值。这样做意味着:

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

那么这和我们的例子有什么关系呢?基本上,表达式通常用于声明单例对象。但是它也可以用来声明一个对象原型,所以稍后有人可以做var newobj=object.create(foo),newobj将foo作为原型。

如果您真的想了解原型继承有多有用,请详细研究它。道格拉斯·克罗克福德在他的一次多次会谈中详细谈到了这一点)。


命名函数没有什么优势

  • 元分析的名称。functionInstance.name会告诉你名字。
  • 更重要的是,名称将打印在堆栈跟踪中。
  • 名字也有助于编写自我记录或识字代码。

命名函数表达式有一个缺点

  • IE有NFE的内存泄漏

除了较少的风格控制之外,函数声明没有缺点


您的问题实际上由两部分组成,因为如果将函数分配给变量或属性,则不必使函数匿名。

命名vs匿名?

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

匿名函数在JavaScript中是一个坏习惯吗?

函数声明与函数表达式?

关于这个问题的那一部分,我建议你参考这个问题,因为它可能比我所能涵盖的更深入地涵盖了这个主题。

var functionname=function()vs function functionname()