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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10081593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:45:25  来源:igfitidea点击:

Are named functions preferred over anonymous functions in JavaScript?

javascript

提问by Billy ONeal

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?

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

回答by Trevor

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 declarationotherwise use expression. I prefer the latter as I typically build object literals with methods as function expressions.

因此,如果您希望将函数提升到顶部,请使用function declaration其他方式使用expression. 我更喜欢后者,因为我通常使用 as 方法构建对象文字function expressions

Named function expressionscan be handy when errors are thrown. The console will tell you what the function is instead of stating anonymousaka stack trace.

function expressions当抛出错误时,命名会很方便。控制台会告诉你这个函数是什么,而不是说明anonymousaka stack trace

回答by rtpg

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 2or [4,5]. This represents a value. So doing var foo=function(){ ... }will work as planned, every time.

function() { ... }是一个函数表达式。从语法上讲,这与2or处于同一级别[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. Hereyou'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

有趣的事实:function 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.

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



Summaryvar 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(){ ... }* 有点 * 与函数相同,foo(){ ... }除了前者做你认为它应该做的事情,而后者做奇怪的事情,除非你把它包在括号里,但这会弄乱作用域,而 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 sortacompletely 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 oneof his many talks).

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

回答by Raynos

There are few advantages to naming functions

命名函数的好处很少

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

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

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

回答by Matt Esch

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() {}