我正在读这本书。 Javascript,道格拉斯·克罗克福德的优秀作品。书中提供了一些例子,但我无法理解这些例子在实践中的用处和方式。为简单起见,我在这里修改了代码。 这里有两种方法,我可以对变量进行函数赋值。
example1:
var test= function(ex) {
alert(ex);
};
test(5);
这会生成值为5的警告框
例2:
var test1 = function test2(ex) {
alert(ex);
};
test1(7); //this produces alert box with value of 7
test2(8)//this does not give a alert box
我已定义了函数test2,但已将其分配给test1。为什么我不能通过调用test2(8)直接访问test2。 此外,我没有看到示例2中的任何大优势超过示例1.如果您有一些差异,其中一个是优越的,我希望听到。
由于
答案 0 :(得分:6)
var test1 = function test2(ex) {
console.log(test2);
};
命名函数使其能够从其体内引用自身。
test2
仅对test2
及其子作用域(函数)可见。如果有的话。
答案 1 :(得分:5)
你基本上是为一个名为test1
的函数分配一个名为“命名函数表达式”的函数。调试代码很有用,因为函数的名称将显示在调用堆栈跟踪中,而不是“匿名函数”。
JavaScript中的函数也是对象,因此函数的标识符是test1
(函数对象),但函数本身的名称为test2
,因此test1.name == 'test2'
答案 2 :(得分:2)
您所指的语法称为named function expression。它主要用于支持匿名函数的递归。
在ECMASCRIPT 5之前的javascript中,当函数是匿名时,有两种方法可以进行递归。
使用arguments.callee:
(function(x){
alert(x);
if (x) {
arguments.callee(x-1);
}
})(10);
使用命名函数表达式:
(function countdown (x){
alert(x);
if (x) {
countdown(x-1);
}
})(10);
在ECMASCRIPT 5中,当启用严格模式时,不再支持arguments.callee
。因此,在ECMASCRIPT 5严格模式和未来版本的javascript中,您应该使用命名函数表达式来编写递归匿名函数。
现在您可能想知道,这不是您要问的语法。该语法如下:
(function foo () { foo })()
你问的是:
var bar = function foo () { foo }
实际上,它们是一样的。命名函数表达式语法适用于函数表达式。这只不过是在表达式上下文中声明的函数。
在javascript中,表达式上下文就是评估数学的任何地方。基本上,表达式上下文是大括号()
之间的任何内容,=
符号右侧的任何内容。以及需要由运营商评估的任何事情。
除了上面的两种形式之外,以下也是有效的命名函数表达式:
!function foo(){ foo };
0==function foo(){ foo };
0?0:function foo(){ foo };
答案 3 :(得分:1)
您希望它的行为方式违反规范。必须命名函数声明,并且它们的名称表示当前范围中的变量。但是,函数表达式在命名时,不应该使用其名称创建变量。相反,它们的名称仅在函数内可用。
一些旧的浏览器(例如IE8)用于将名称泄露为变量,请参阅Named function expressions demystified。
答案 4 :(得分:-1)
您的示例2并不是正确JavaScript的示例。定义函数有两种方法:
和
请注意,在第一个示例中,您首先有效地创建匿名函数,然后然后您将一个名称(' foo')附加到该函数匿名函数对象。但是,在第二个示例中,您正在创建一个命名的函数对象' foo'马上。
另外,如果你去控制台并按照你的方式首先定义test2,然后在定义之后输入行var test1 = test2
,那么你将拥有这两个函数。 / p>
你可以在另一个S / O答案中看到更深层次的技术差异的解释,非常赞成:var functionName = function() {} vs function functionName() {}