为变量分配非匿名函数

时间:2014-08-13 12:11:51

标签: javascript function

在我正在阅读的一本书中,有一个关于递归的页面,其中包含以下代码:

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。为什么河内被宣布为变量,而且这个功能被命名为河内?为什么“河内”加倍?

5 个答案:

答案 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*/ }

将创建两个变量hanoihanoi2,它们都引用相同的函数。但是,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)

分别是FunctionExpressionFunctionDeclaration之间的区别。

  1. 在第一种情况下,函数是表达式。为什么?只能将表达式赋值给变量。
  2. 在第二种情况下,函数是声明。为什么?它不是用在表达式的上下文中。
  3. 唯一明显的区别是,您可以在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的旧版本有内存泄漏,它使用额外的字节。