在javascript中这种函数赋值给变量有用吗?

时间:2013-06-18 00:56:32

标签: javascript function object

我正在读这本书。 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.如果您有一些差异,其中一个是优越的,我希望听到。

由于

5 个答案:

答案 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中,当函数是匿名时,有两种方法可以进行递归。

  1. 使用arguments.callee:

    (function(x){
        alert(x);
        if (x) {
            arguments.callee(x-1);
        }
    })(10);
    
  2. 使用命名函数表达式:

    (function countdown (x){
        alert(x);
        if (x) {
            countdown(x-1);
        }
    })(10);
    
  3. 在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的示例。定义函数有两种方法:

  • var foo = function(x){console.log(x);返回x; }

  • function foo(x){console.log(x);返回x; }

请注意,在第一个示例中,您首先有效地创建匿名函数,然后然后您将一个名称(' foo')附加到该函数匿名函数对象。但是,在第二个示例中,您正在创建一个命名的函数对象' foo'马上。

另外,如果你去控制台并按照你的方式首先定义test2,然后在定义之后输入行var test1 = test2,那么你将拥有这两个函数。 / p>

你可以在另一个S / O答案中看到更深层次的技术差异的解释,非常赞成:var functionName = function() {} vs function functionName() {}