在下面的第一个片段中,根据我的理解,我正在创建一个函数并将其分配给一个变量。但这是否意味着该函数将采用该变量的名称?
var aFunc = function(){};
我知道这是命名函数。
function bFunc(){};
在下面的第一个片段中,根据我的理解,我正在创建一个函数并将其分配给一个变量。但这是否意味着该函数将采用该变量的名称?
var aFunc = function(){};
我知道这是命名函数。
function bFunc(){};
不。
在第一个示例中,您正在创建一个匿名函数,然后将其分配给“aFunc”
在第二个示例中,您声明了一个函数并将其称为 bFunc。
两者之间最显着的区别是您不能在分配它的行之后调用“aFunc”。
不,该函数不会“取变量名”。该变量将保存对匿名函数的引用。该函数本身仍然是匿名的。
请注意,这最终几乎没有什么区别,这个函数引用一旦被分配,就可以被视为与任何常规命名函数完全相同。事实上,它几乎没有什么区别,一个命名函数也可以被视为一个持有函数引用的变量:
function foo() { }
foo();
foo = 'bar';
alert(foo); // bar
“匿名函数”这个术语是行话,所以它的含义很可能会随着时间而改变。没有说明它是什么的规范,所以它可以是你想要的任何东西。无论您做出什么决定,都可能会受到其他人的争议。行话就是这样(查找“中继”一词,这是电话中的一个常见术语)。
严格来说,有些函数声明的名称是强制性的,例如
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(){};
实际上无法区分,主要区别在于创建函数的时间。
因此,首先我们必须澄清您编写的两个函数之间的主要区别。
这个:
var aFunc = function(){};
是一个函数表达式。这个在哪里:
function bFunc(){};
是一个函数声明。
在函数表达式中,您使用函数运算符在表达式中定义函数。当你声明一个函数时,你正在使用函数语句。
一开始可能会令人困惑,因为它们非常相似,但是函数声明和函数表达式的行为不同。首先,您不能声明匿名函数:如果您使用函数语句,则名称是必需的。所以只有用函数运算符定义的函数可以是匿名的:
var aFunc = function(){};
那是一个匿名函数。在某些浏览器中,您实际上可以打印函数的名称并自己查看:
console.log(aFunc.name);
(请注意,这还不是标准,但有一个提案)
但这并不意味着用函数运算符声明的函数必须是匿名的。例如:
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);
因此,您不会使用许多仅用于类似目的的函数来污染范围,并且您仍然可以从函数的主体访问该函数。arguments.callee
这在不推荐使用的 ES5 和递归中特别有用。
函数表达式之间的另一个区别是您可以立即调用它们,但不能对函数声明执行此操作。因此,例如:
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;
一元取反操作和值-
在哪里:他们对 什么一无所知,对吧?与函数表达式完全相同,运算符在哪里,值是哪里。3
aFunc
function
(){}