在我正在阅读的一本书中,有一个关于递归的页面,其中包含以下代码:
var hanoi = function hanoi(disc, src, aux, dst){
if (disc > 0){
hanoi(disc - 1, src, dst, aux);
document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
hanoi(disc - 1, aux, src, dst);
}
};
修改:问题改写 - 在此示例中,var hanoi = function hanoi(){}
与仅使用var hanoi = function(){}
之间的区别是什么?
E.g。为什么河内被宣布为变量,而且这个功能被命名为河内?为什么“河内”加倍?
答案 0 :(得分:1)
首先,您不需要命名该功能。这就足够了:
var hanoi = function() { /*code*/ }
然而,在处理变量提升和声明函数的方式时,是的区别。
例如,以下代码将无错误地使用:
foo();
function foo(){
console.log('foo');
}
然而这不会运行:
foo();
var foo = function(){
console.log('foo');
}
第二个例子会出现“undefined is not a function”之类的错误。
函数声明(function foo() {}
)与函数的完整主体一起被提升,而var语句只有变量被提升到范围的顶部。
编辑:请注意,这里有一些摆动空间:
var hanoi2 = function hanoi() { /*code*/ }
将创建两个变量hanoi
和hanoi2
,它们都引用相同的函数。但是,hanoi
将作为完整功能提升,但hanoi2
不会。
答案 1 :(得分:1)
var hanoi = function hanoi(){}
创建一个命名函数表达式,并将其分配给一个名称恰好与表达式名称相同的变量。
function hanoi(){}
声明一个函数。
这两种结构的悬挂方式有所不同。例如,您可以在声明之前调用声明的函数。但你不能对命名函数表达式做同样的事情。
//ok
var joe = new Person();
function Person() {};
//error
var joe = new Person();
var Person = function Person(){};
答案 2 :(得分:1)
分别是FunctionExpression
和FunctionDeclaration
之间的区别。
唯一明显的区别是,您可以在FunctionDeclaration
出现在当前范围之前使用它。这是因为声明在JavaScript中提升。例如:
alert(f()); // Error: undefined is not a function.
var f = function f() { return "Hello World!"; };
在我们调用f
时,尚未定义变量f
。因此它会引发错误。
alert(f()); // Hello World!
function f() { return "Hello World!"; };
这里我们可以在它出现在当前范围之前调用f
,因为JavaScript中的声明被提升(即放到范围的顶部)。
我个人更喜欢使用函数声明而不是函数表达式。您甚至可以在函数中的return
语句之后放置函数声明,并仍然在return
语句之前调用它们。这允许您使用模块模式编写可读模块。
答案 3 :(得分:1)
这里有一个非常微妙的观点。在以下两个示例中,函数的主体与原始主体相同。在一种情况下,使用匿名函数,而在另一种情况下,函数被命名为“hanoi”,就像在原始函数中一样。
var hanoi2 = function hanoi(disc, src, aux, dst){
if (disc > 0){
hanoi(disc - 1, src, dst, aux);
document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
hanoi(disc - 1, aux, src, dst);
}
};
var hanoi3 = function(disc, src, aux, dst){
if (disc > 0){
hanoi(disc - 1, src, dst, aux);
document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
hanoi(disc - 1, aux, src, dst);
}
};
其中任何一个都有效吗?请注意,该功能的主体仍然指的是“hanoi”,而不是“hanoi2”或“hanoi3”。
事实证明hanoi2会起作用,但hanoi3不会。这是因为当您命名函数时,函数的名称在函数体的范围内可用。所以,在你的原始例子和hanoi2中,函数内部的“hanoi”并不是指全局变量hanoi而是指命名函数hanoi。
因此,您的问题的答案是因为函数使用递归,所以命名版本比修改代码时的匿名版本稍强一些。
答案 4 :(得分:0)
在这种情况下,该功能不会被提升。提升意味着在运行任何其他代码之前对其进行编译。仅对功能块进行提升。
我认为没有任何理由在这里做到这一点。你失去了吊装,IE的旧版本有内存泄漏,它使用额外的字节。