JavaScript中“匿名函数”和“函数字面量”的区别是什么?

9

书籍《学习JavaScript》将匿名函数定义如下...

Functions are objects. As such, you can create them - just like a String or Array or other type - by using a constructor and assigning the function to a variable. In the following code, a new function is created using the Function constructor, with the function body and argument passed in as arguments:

var sayHi = new Function("toWhom", "alert('Hi' + toWhom);");

This type of function is often referred to as an anonymous function because the function itself isn't directly declared or named.

这是JavaScript中“匿名函数”的正确定义吗?如果不是,什么是匿名函数,匿名函数和函数字面量之间有什么区别?

这不是最常被称为“匿名”的函数类型。那应该是使用没有名称的FunctionExpression,例如:var fn = function(){..}var fn = function fn(){...}的区别。 - Sean Kinsey
我不认为这是一本好书,但我只能依靠这个片段来做出判断。 - Marcel Korpel
5个回答

18

函数表达式和函数声明

既然您对函数有兴趣,这里有一些重要的知识需要了解。

var abc = function() { ... } 被称为 函数表达式。该变量在执行时将被分配匿名函数,但其变量声明将被提升到当前执行上下文(作用域)的顶部。

但是,一个函数表达式也可以被赋予一个名称,以便在其内部调用它以使其成为递归函数。请记住,IE 存在一些问题。当你给它一个名称时,它绝不是匿名函数。

function abc() { ... } 这样的函数被称为 函数声明。它的定义会被提升到其作用域的顶部。它的名称在内部及其父级作用域中都可用。

更多阅读


你的示例

它是一个匿名函数,但被赋值给变量 sayHi

正如Šime Vidas所提到的,使用 new 运算符实例化了一个新的Function对象,并将参数和函数体作为字符串传递。生成的对象被赋值给 sayHi

使用该方法创建函数的真实世界用途很少(尽管可能只是为了帮助显示函数是对象)。我还相信,将其参数列表和函数体作为字符串传递将调用一个类似于 eval() 的函数,而当有更好的结构可用时,这种做法很少是好的。

此外,使用 Function 创建的函数不形成闭包

我只会在某些情况下使用此方法,例如我需要创建一个Function,并且其参数和/或函数体仅能以字符串形式提供给我时。

在实际应用中,您可以...

var sayHi = function(toWhom) {
   alert('Hi' + toWhom);
};

还可以参考FelixŠime的评论,以进行深入讨论和进一步澄清。


3
@Richard说:“我很少听到函数文字。”重要的是理解函数表达式函数声明之间的区别。如果我们将函数表达式视为函数文字,那么它们并不相同。就像@alex已经解释的那样,有一种命名函数表达式,它们不再是匿名的,函数有一个名称。但它们仍然是函数表达式(=函数文字)。 - Felix Kling
1
@alex "这被称为函数表达式。" - 不,它是通过使用Function构造函数创建的函数对象。函数表达式是这样的:function Identifieropt ( FormalParameterListopt ) { FunctionBody } - Šime Vidas
@alex:对我来说很好 :) 也许你可以强调命名函数表达式不是匿名的(显然,但为了清晰起见)。但我不能再给你+1了 ;) - Felix Kling
@Felix Kling - 我同意@alex的答案很好...除了“它是一个匿名函数,但被分配给变量sayHi”这句话对我来说没有意义。一旦它被分配给一个变量,我不明白它如何仍然是匿名的。在JavaScript中,function myFunk() {...}var myFunk = function() {...}相同,对吗?因此,将匿名函数分配给变量与声明并命名它相同,因此不再是匿名的。 - Richard JP Le Guen
1
@RichardJPLeGuen:我认为函数声明会向定义函数的作用域中添加一个新符号。这个符号与函数名相同。考虑另一个例子:function a(){}; var b = a;。尽管函数被分配给了b,但它的名称仍然是a。我建议您查看函数的name属性(在Chrome中也适用),以了解哪个语句生成了什么类型的函数。 - Felix Kling
显示剩余19条评论

1

匿名函数就是一个没有名称的函数。

function(a, b){
  return a + b;
}

以上代码是无用的,因为它没有名称可以调用。所以通常会将它们分配给一个变量。
var func = function(a, b){
  return a + b;
}

这很有帮助,因为您可以将匿名函数传递给另一个函数或方法,而无需事先创建该函数,如下所示。

function bob(a){
  alert(a());
}

bob(function(){
  return 10*10;
})

1
@Sean_Kinsey 正是,这就是为什么我说它是无用的,并继续展示了如何与其他代码结合使用。 - Ryan

1

这个:

new Function("toWhom", "alert('Hi' + toWhom);")

还有这个:

function(toWhom) { alert('Hi' + toWhom); }

这是两个产生相同结果的表达式 - 它们返回一个新的匿名函数对象。

第二个表达式(仅限第二个表达式)被称为函数表达式。您也可以称其为函数字面量(尽管我们可以争论函数声明也是函数字面量)。


1

我认为一个更广泛且更被接受的匿名函数定义是指创建时没有名称的函数。


0
function foo(){
    alert("i'm foo, nice to meet you!");
}
var bar = function(){
    alert("I am an anonymous function assigned to the variable \"bar\"");
}

那么匿名函数是函数字面量的同义词吗? - Richard JP Le Guen
2
@Richard - 除非你指的是JavaScript中函数的正式语法,否则不存在“函数文字”。另一种方法是使用Function构造函数创建函数。 在js中,您有三种创建函数的方式,使用FunctionDeclaration(名称必填),FunctionExpressions(名称可选)和FunctionConstructor(名称可选)。后两者具有可选名称,因为它们可以用于表达式,并因此被称为操作数。 - Sean Kinsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接