在javascript中,这种函数赋值给变量是有用的

where in javascript is this kind of function assignment to variable useful?

本文关键字:变量 有用 赋值 函数 javascript      更新时间:2023-09-26

我正在看书。Javascript, Douglas Crokford的《The good parts》。书中提供了一些例子,但我不明白这些例子在实践中在哪里以及如何有用。为了简单起见,我修改了这里的代码。这里有两种方法,我可以对变量进行函数赋值。

例二:

var test= function(ex) {
    alert(ex);
};
test(5);

这会产生值为5的警告框

example2:

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有什么大的优势。如果你们有不同之处,而且其中一个更好,我愿意听听。

谢谢

var test1 = function test2(ex) {
    console.log(test2);
};

给函数命名使其能够从函数体内部引用自己。

test2仅对test2及其子作用域(函数)可见(如果有的话)。

你基本上是给test1分配一个名字的函数,这就是所谓的"命名函数表达式"。这对调试代码很有用,因为函数的名称将出现在调用堆栈跟踪中,而不是"匿名函数"。

JavaScript中的函数也是对象,所以函数的标识符是test1(函数对象),但是函数本身的名称是test2,所以test1.name == 'test2'

您引用的语法称为命名函数表达式。它主要用于支持匿名函数中的递归。

在ECMASCRIPT 5之前的javascript中,当函数是匿名的时候,有两种递归方法。

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

    (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 };

您希望它的行为方式是违反规范的。函数声明必须命名,它们的名字表示当前作用域中的变量。但是函数表达式,当被命名时,不应该用它们的名字创建一个变量。相反,它们的名称只在函数内部可用。

一些旧的浏览器(例如IE8)曾经将名称泄漏为变量,请参见揭秘命名函数表达式。

你的例子2并不是真正正确的JavaScript的例子。有两种定义函数的方法:

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

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

注意,在第一个示例中,您首先有效地创建了一个匿名函数,然后为该匿名函数对象附加了一个名称('foo')。然而,在第二个示例中,您立即创建了一个命名函数对象'foo'。

同样,如果您进入控制台并按照您的方式首先定义test2,然后,在定义之后,输入var test1 = test2行,那么您将有两个函数可用。

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