JavaScript中是否首选命名函数或匿名函数? [重复]

时间:2021-01-03 22:29:19

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

可能重复:JavaScript:var functionName = function(){} vs function functionName(){}

There are two possible methods for pulling out a function in Javascript:

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

var foo = function() { ... }

(this is a bit contrived; another common pattern is:

(这有点人为;另一个常见的模式是:

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

)

versus

function foo() { ... }

Is there an explicit reason to prefer one or the other?

是否有明确的理由偏好一个或另一个?

4 个解决方案

#1


68  

It all comes down to preference to where you declare your functions; hoisting.

这一切都取决于你声明你的功能的地方;吊装。

Function declarations and variable declarations are always moved ("hoisted") invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:

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

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

is actually interpreted like this:

实际上解释如下:

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

Notice that the assignment portion of the declarations were not hoisted. Only the name is hoisted. This is not the case with function declarations, where the entire function body will be hoisted as well.

请注意,声明的赋值部分未被提升。只有名字被悬挂。函数声明不是这种情况,整个函数体也将被提升。

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();

In this case, only the function declaration has its body hoisted to the top. The name 'foo' is hoisted, but the body is left behind, to be assigned during execution.

在这种情况下,只有函数声明将其主体提升到顶部。名称'foo'被悬挂,但身体被遗忘,在执行期间被分配。

You can give names to functions defined in function expressions, with syntax like a function declaration. This does not make it a function declaration, and the name is not brought into scope, nor is the body hoisted.

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

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"

So, if your preference is to have functions hoist to the top use a function declaration otherwise use expression. I prefer the latter as I typically build object literals with methods as function expressions.

因此,如果您的偏好是将函数提升到顶部,则使用函数声明,否则使用表达式。我更喜欢后者,因为我通常用方法作为函数表达式构建对象文字。

Named function expressions can be handy when errors are thrown. The console will tell you what the function is instead of stating anonymous aka stack trace.

抛出错误时,命名函数表达式可以很方便。控制台将告诉您该函数是什么,而不是声明匿名也称为堆栈跟踪。

#2


9  

You've hit on a couple different things here, but I'll try to hit your main question first.

你在这里遇到了几件不同的事情,但我会先尝试解决你的主要问题。

In general....

一般来说....

function() { ... } is a function expression. Syntaxically this is on the same level as 2 or [4,5]. This represents a value. So doing var foo=function(){ ... } will work as planned, every time.

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

function foo() { ... } is a function declaration. This might seem to do the same thing as var foo=function(){...}, but there's a small caveat. As its a declaration, it works similar to the concept of variable hoisting in JS (basically, all variable declarations are done before any expressions are evaluated).

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

A good example is from here:

一个很好的例子来自这里:

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();

Basically variable hoisting has brought the value up to the top, so this code is equivalent (in theory) to :

基本上可变的提升使得价值达到顶峰,因此这段代码(理论上)与以下内容相同:

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

NB: I'd like to take this spot to say that JS interpreters have a hard time following theory, so trusting them on somewhat iffy behaviour is not recommended. Here you'll find a good example at the end of a section where theory and practice end up not working (there are also some more details on the topic of expressions vs declarations).

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

Fun fact: wrapping function foo() {...} in parentheses transforms it from a declaration to an expression, which can lead to some weird looking code like

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

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

Don't do this if you don't have a reason to, please.

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


Summary var foo=function(){ ... } is *sorta kinda * the same as function foo(){ ... } except that the former does what you think it does where you think it should whereas the latter does weird stuff unless you wrap it in parens, but that messes up the scope, and JS interpreters allow you to do things that are considered syntax errors in the spec so you're led to believe that wrong things are in fact right, etc....

总结var foo = function(){...}是* sorta有点*与函数foo(){...}相同,除了前者做你认为应该做的事情,而后者做了奇怪的东西除非你将它包装在parens中,但这会影响范围,并且JS解释器允许你在规范中执行被认为是语法错误的事情,因此你会被认为错误的事情实际上是对的,等等....

please use function expressions( var f=function(){...} ). There's no real reason not to, especially considering you're somewhat forced to do it when you're using dot syntax.

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


On to the second thing you touched.....

到了你触及的第二件事.....

I'm not really sure what to say, it's kinda sorta completely different from everything else about this.

我不太确定该说些什么,它与其他一切完全不同。

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

this is known as object literal syntax. JSON, which is based off of this syntax, is a pretty neat way of formatting data, and this syntax in JS is often used to declare new objects, with singleton objects for example(avoiding all the mess with declaring a function and using new ). It can also be used in the same way XML is used, and is preferred by all the cool kids...

这称为对象文字语法。基于这种语法的JSON是一种非常简洁的格式化数据的方式,JS中的这种语法通常用于声明新对象,例如单例对象(避免声明函数和使用new的所有混乱) 。它也可以像使用XML一样使用,并且是所有酷孩子的首选......

Anyways, basically object literal syntax works like this:

无论如何,基本上对象文字语法的工作原理如下:

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

This expression is an object with certain values initialised on it. so doing var obj={ name1: val1, .... namek:valk } means that :

此表达式是在其上初始化某些值的对象。所以做var obj = {name1:val1,.... namek:valk}意味着:

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

So what does this have to do with our example? Basically your expression is often used to declare singleton objects. But it can also be used to declare an object prototype, so someone can later do var newObj=Object.create(foo) , and newObj will have foo as a prototype.

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

Look into prototypal inheritence in detail if you want to really get how useful it is. Douglas Crockford talks about it in detail in one of his many talks).

如果你想真正了解它的实用性,请详细研究原型继承。道格拉斯·克罗克福德(Douglas Crockford)在他的众多会谈中详细谈到了这一点。

#3


2  

There are few advantages to naming functions

命名函数几乎没有什么优势

  • names for meta analysis. functionInstance.name will show you the name.
  • 元分析的名称。 functionInstance.name将显示名称。
  • Far more importantly, the name will be printed in stack traces.
  • 更重要的是,名称将以堆栈跟踪打印。
  • names also help write self documenting or literate code.
  • 名称也有助于编写自我记录或识字代码。

There is a single disadvantage to named functions expressions

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

  • IE has memory leaks for NFE
  • IE有NFE的内存泄漏

There are no disadvantages to function declarations apart from less stylistic control

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

#4


0  

Your question really comprises of two parts, as you don't necessarily have to make your functions anonymous if they are assigned to a variable or property.

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

Named vs anonymous?

命名为匿名?

@Raynos highlights the main points clearly. The best part about named functions is that they will show themselves in a stack trace. Even in situations where functions are being assigned to variables/properties, it's a good idea to give your functions a name just to aid with debugging, however I wouldn't say anonymous functions are evil at all. They do serve a fine purpose:

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

Are anonymous functions a bad practice in JavaScript?

匿名函数在JavaScript中是不好的做法吗?

Function declaration vs function expression?

函数声明与函数表达式?

For that part of the question I would refer you to this question as it probably covers the topic in far more depth than I can

对于问题的这一部分,我会向您推荐这个问题,因为它可能比我更深入地涵盖了这个主题

var functionName = function() {} vs function functionName() {}

var functionName = function(){} vs function functionName(){}

#1


68  

It all comes down to preference to where you declare your functions; hoisting.

这一切都取决于你声明你的功能的地方;吊装。

Function declarations and variable declarations are always moved ("hoisted") invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:

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

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

is actually interpreted like this:

实际上解释如下:

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

Notice that the assignment portion of the declarations were not hoisted. Only the name is hoisted. This is not the case with function declarations, where the entire function body will be hoisted as well.

请注意,声明的赋值部分未被提升。只有名字被悬挂。函数声明不是这种情况,整个函数体也将被提升。

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();

In this case, only the function declaration has its body hoisted to the top. The name 'foo' is hoisted, but the body is left behind, to be assigned during execution.

在这种情况下,只有函数声明将其主体提升到顶部。名称'foo'被悬挂,但身体被遗忘,在执行期间被分配。

You can give names to functions defined in function expressions, with syntax like a function declaration. This does not make it a function declaration, and the name is not brought into scope, nor is the body hoisted.

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

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"

So, if your preference is to have functions hoist to the top use a function declaration otherwise use expression. I prefer the latter as I typically build object literals with methods as function expressions.

因此,如果您的偏好是将函数提升到顶部,则使用函数声明,否则使用表达式。我更喜欢后者,因为我通常用方法作为函数表达式构建对象文字。

Named function expressions can be handy when errors are thrown. The console will tell you what the function is instead of stating anonymous aka stack trace.

抛出错误时,命名函数表达式可以很方便。控制台将告诉您该函数是什么,而不是声明匿名也称为堆栈跟踪。

#2


9  

You've hit on a couple different things here, but I'll try to hit your main question first.

你在这里遇到了几件不同的事情,但我会先尝试解决你的主要问题。

In general....

一般来说....

function() { ... } is a function expression. Syntaxically this is on the same level as 2 or [4,5]. This represents a value. So doing var foo=function(){ ... } will work as planned, every time.

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

function foo() { ... } is a function declaration. This might seem to do the same thing as var foo=function(){...}, but there's a small caveat. As its a declaration, it works similar to the concept of variable hoisting in JS (basically, all variable declarations are done before any expressions are evaluated).

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

A good example is from here:

一个很好的例子来自这里:

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();

Basically variable hoisting has brought the value up to the top, so this code is equivalent (in theory) to :

基本上可变的提升使得价值达到顶峰,因此这段代码(理论上)与以下内容相同:

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

NB: I'd like to take this spot to say that JS interpreters have a hard time following theory, so trusting them on somewhat iffy behaviour is not recommended. Here you'll find a good example at the end of a section where theory and practice end up not working (there are also some more details on the topic of expressions vs declarations).

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

Fun fact: wrapping function foo() {...} in parentheses transforms it from a declaration to an expression, which can lead to some weird looking code like

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

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

Don't do this if you don't have a reason to, please.

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


Summary var foo=function(){ ... } is *sorta kinda * the same as function foo(){ ... } except that the former does what you think it does where you think it should whereas the latter does weird stuff unless you wrap it in parens, but that messes up the scope, and JS interpreters allow you to do things that are considered syntax errors in the spec so you're led to believe that wrong things are in fact right, etc....

总结var foo = function(){...}是* sorta有点*与函数foo(){...}相同,除了前者做你认为应该做的事情,而后者做了奇怪的东西除非你将它包装在parens中,但这会影响范围,并且JS解释器允许你在规范中执行被认为是语法错误的事情,因此你会被认为错误的事情实际上是对的,等等....

please use function expressions( var f=function(){...} ). There's no real reason not to, especially considering you're somewhat forced to do it when you're using dot syntax.

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


On to the second thing you touched.....

到了你触及的第二件事.....

I'm not really sure what to say, it's kinda sorta completely different from everything else about this.

我不太确定该说些什么,它与其他一切完全不同。

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

this is known as object literal syntax. JSON, which is based off of this syntax, is a pretty neat way of formatting data, and this syntax in JS is often used to declare new objects, with singleton objects for example(avoiding all the mess with declaring a function and using new ). It can also be used in the same way XML is used, and is preferred by all the cool kids...

这称为对象文字语法。基于这种语法的JSON是一种非常简洁的格式化数据的方式,JS中的这种语法通常用于声明新对象,例如单例对象(避免声明函数和使用new的所有混乱) 。它也可以像使用XML一样使用,并且是所有酷孩子的首选......

Anyways, basically object literal syntax works like this:

无论如何,基本上对象文字语法的工作原理如下:

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

This expression is an object with certain values initialised on it. so doing var obj={ name1: val1, .... namek:valk } means that :

此表达式是在其上初始化某些值的对象。所以做var obj = {name1:val1,.... namek:valk}意味着:

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

So what does this have to do with our example? Basically your expression is often used to declare singleton objects. But it can also be used to declare an object prototype, so someone can later do var newObj=Object.create(foo) , and newObj will have foo as a prototype.

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

Look into prototypal inheritence in detail if you want to really get how useful it is. Douglas Crockford talks about it in detail in one of his many talks).

如果你想真正了解它的实用性,请详细研究原型继承。道格拉斯·克罗克福德(Douglas Crockford)在他的众多会谈中详细谈到了这一点。

#3


2  

There are few advantages to naming functions

命名函数几乎没有什么优势

  • names for meta analysis. functionInstance.name will show you the name.
  • 元分析的名称。 functionInstance.name将显示名称。
  • Far more importantly, the name will be printed in stack traces.
  • 更重要的是,名称将以堆栈跟踪打印。
  • names also help write self documenting or literate code.
  • 名称也有助于编写自我记录或识字代码。

There is a single disadvantage to named functions expressions

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

  • IE has memory leaks for NFE
  • IE有NFE的内存泄漏

There are no disadvantages to function declarations apart from less stylistic control

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

#4


0  

Your question really comprises of two parts, as you don't necessarily have to make your functions anonymous if they are assigned to a variable or property.

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

Named vs anonymous?

命名为匿名?

@Raynos highlights the main points clearly. The best part about named functions is that they will show themselves in a stack trace. Even in situations where functions are being assigned to variables/properties, it's a good idea to give your functions a name just to aid with debugging, however I wouldn't say anonymous functions are evil at all. They do serve a fine purpose:

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

Are anonymous functions a bad practice in JavaScript?

匿名函数在JavaScript中是不好的做法吗?

Function declaration vs function expression?

函数声明与函数表达式?

For that part of the question I would refer you to this question as it probably covers the topic in far more depth than I can

对于问题的这一部分,我会向您推荐这个问题,因为它可能比我更深入地涵盖了这个主题

var functionName = function() {} vs function functionName() {}

var functionName = function(){} vs function functionName(){}