这是一个匿名函数吗?

时间:2013-04-11 01:54:20

标签: javascript

在下面的第一个片段中,基于我的理解,我正在创建一个函数并将其分配给变量。但这是否意味着该函数将采用该变量的名称?

var aFunc = function(){};

我知道这是命名函数。

function bFunc(){};

5 个答案:

答案 0 :(得分:3)

没有

在第一个示例中,您将创建一个匿名函数,然后将其分配给“aFunc”

在第二个例子中,你声明一个函数并将其命名为bFunc。

两者之间最显着的区别是你不能在分配它之前调用“aFunc”。

答案 1 :(得分:3)

不,该功能不会“取变量的名称”。该变量将保存对匿名函数的引用。该功能本身仍然是匿名的。

请注意,这在最后几乎没有什么区别,但是这个函数引用一旦被赋值,就可以被视为与任何常规命名函数完全相同。实际上,它的差别很小,命名函数也可以像持有函数引用的变量一样对待:

function foo() { }
foo();
foo = 'bar';
alert(foo); // bar

答案 2 :(得分:3)

术语“匿名函数”是行话,所以它的意思很可能会随着时间而改变。没有规范说明它是什么,所以它可以是你想要的任何东西。无论你决定什么,都可能会受到其他人的质疑。术语就像那样(查看“trunking”这个词,这是电话中常用的术语)。

严格来说,有一些函数声明,其中名称是必需的,例如

function foo() {
    ...
}

和函数表达式,其中名称是可选的。如果名称丢失,例如:

var x = function () {
             ...
        };
那么,对我来说,这是一个匿名函数。如果它有一个名字,例如

var x = function foo() {
             ...
        };

然后它是一个命名函数表达式(而不是匿名函数)。从我的角度来看,任何没有可选名称的函数表达式都是匿名函数。函数表达式有很多用途,例如

// assignment to a variable
var x = function() {...}

// pass as a parameter
foo(function(){...})

// immediately executed and pass the result
foo( (function(){...}()) )

等等。所以在OP中,赋值的右边是一个没有名字的函数表达式,所以对我来说,这是一个匿名函数。然后将其分配给标识符的事实不会突然使其成为命名函数表达式。

其他人可能会有所不同。

顺便提一下,结果:

function foo(){}

var foo = function(){};

几乎无法区分,主要区别在于创建函数时。

答案 3 :(得分:3)

因此,首先我们要澄清你所写的两个函数之间的主要区别。

这一个:

var aFunc = function(){};

函数表达式。这一个:

function bFunc(){};

函数声明

函数表达式中,您使用function operator来定义表达式中的函数。 当您声明一个函数时,您正在使用function statement

一开始它可能会让人感到困惑,因为它们非常相似,但函数声明和函数表达式表现不同。首先,您不能声明一个匿名函数:如果您使用的是函数语句,则该名称是必需的。 因此,只有使用函数运算符定义的函数才能是匿名的:

var aFunc = function(){};

这是一个匿名函数。在某些浏览器中,您实际上可以打印function's name并自己查看:

console.log(aFunc.name); 

(请注意,这还不是标准,但有一个proposal

但这并不意味着用函数运算符声明的函数必须是匿名的。例如:

var aFunc = function myFunction() {};

这是一个命名函数。但是,这仍然与具有这样的函数声明不同:

function myFunction() {};
var aFunc = myFunction;

为什么呢?因为在函数表达式的情况下,您不在范围中声明myFunction函数:

var aFunc = function myFunction() {};

console.log(typeof myFunction) // undefined, unless some bugs

那么为函数表达式命名是什么意思?答案是:从函数体本身访问该函数,而不会污染范围。例如,您想要将事件侦听器添加到DOM节点,但只执行一次侦听器:

document.body.addEventListener("click", function onclick() {
    // do something
    document.body.removeEventListener("click", onclick, false);
}, false);

因此,您不会使用许多仅用于此类目的的函数来污染范围,并且您仍然可以从函数体中访问该函数。这在ES5中特别有用,其中arguments.callee已被弃用,以及递归。

函数表达式之间的另一个区别是您可以立即调用它们,但是您不能为函数声明执行此操作。所以,例如:

function() {
    console.log('foo');
}();

将抛出异常,因为引擎无法理解它是函数声明还是函数表达式。但是如果你强迫引擎把它看作一个表达式:

!function() {
    console.log('foo');
}();

// or
(function(){
    console.log('foo');
}());

// etc, there are a lot of ways

我们在这里:JS理解是一个表达式,因此威胁function作为运算符而不是语句。并且您获得了IIFE(立即调用的函数表达式),它在许多场景中都很有用,特别是在您想要隔离代码的地方。

那么,回到你的问题,为什么这个函数的名称:

var aFunc = function(){};

不是aFunc

因为,这是一个表达。所以该值对左侧的赋值一无所知。这就像是:

var aFunc = -3;

-Unary Negation operation3是值:他们对aFunc一无所知,对吧?它与函数表达式完全相同,其中function是运算符,(){}是值。

答案 4 :(得分:2)

不,不是。第一个语句的右侧是函数表达式。只要您不将其分配给变量,它就是匿名的。

分配完成后,可以将其用作声明的功能。

查看有关函数声明in this question

的更多详细信息