在Douglas Crockford的书中,他写了一个递归函数:
var walk_the_DOM = function walk(node, func){
func(node);
node = node.firstChild;
while(node){
walk(node,func);
node = node.nextSibling;
}
}
我从未见过定义为var foo = function bar(){...}
的函数 - 我一直认为声明的右边是匿名者:var foo = function (){...}
声明右侧名称walk
的唯一目的是缩短walk_the_DOM
的号码吗?它们似乎成为相同功能的独立名称。也许我误解了这个片段是如何工作的。
在变量声明和函数构造中是否存在命名函数的功能原因?
答案 0 :(得分:4)
在变量声明和函数构造中是否存在命名函数的功能性原因?
是。 function bar() {}
会将函数的name
属性设置为bar
,这对于(例如)在堆栈跟踪中进行调试非常有用。
关于您提到的一些命名混淆,这可能会有所帮助:
function bar() {}
^这是函数声明,因为它不作为赋值表达式的一部分存在。
var foo = function() {};
^这是赋值表达式,其中右侧操作数是函数表达式,其中函数表达式定义匿名函数
var foo = function bar() {};
^这是赋值表达式,其中右侧操作数是函数表达式,其中函数表达式定义命名函数
可能值得注意的是,函数声明可以通过其函数名在本地引用,因此以下语句大致等效:
function bar() {}
var bar = function() {};
我说大致等价,因为第二个语句仍会产生匿名函数,而不是名为的函数。函数声明如何被提升也有细微的差别。请考虑以下内容,例如:
function test() {
hello();
var hello = function () { console.log('hello'); };
}
test();
// > TypeError: hello is not a function
请注意hello
在技术上已经定义了我们尝试调用它的地方(例外情况只是它不是一个功能(还))。这是由于可变吊装。但是,正如预期的那样,我们还没有将我们的函数分配给hello
变量。真的,这比解释更容易。基本上,由于提升,上述test
示例相当于:
function test() {
var hello; // declared, but not assigned yet
hello();
hello = function () { console.log('hello'); }; // now the assignment happens
}
将其与实际的函数声明进行比较:
function test() {
hello();
function hello() { console.log('hello'); };
}
test();
// > "hello"
请注意,即使声明在下面调用命令,它仍然有效,因为函数声明作为一个整体被提升到其作用域的顶部(在这种情况下,test
)。
如果这令人困惑,这里有一个更为简洁的行为描述可能会有所帮助:声明被提升,而非分配。只要你理解了函数声明和函数表达式之间的区别,那就是你需要知道的全部内容。 :)
答案 1 :(得分:2)
通过编写var foo = function (){...}
,您声明了一个名为foo
的变量,它包含一个匿名函数。通过编写var foo = function bar(){...}
,您将声明一个名为foo
的变量,该变量将命名函数保存为bar
。正如@ jmar777在他的回答中指出的那样,在调试和修复错误时跟踪堆栈跟踪很有用。