2

在我开始的另一个线程的评论中,有人说:

@adlwalrus 是的。试试这个: var foo = function bar(){}; 控制台.log(foo); 但是请注意, bar 只是函数名称(这意味着我自己不确定)而不是对它的引用,因此您不能通过执行 bar() 来调用它。并且分配(甚至命名函数)与声明函数不同。提升(撞到范围顶部)仅适用于声明,分配将保持不变。– 瓦伦蒂娜斯 6 小时前

如果你不能用函数名来调用它,它的用途是什么bar()

4

3 回答 3

4

您指的是命名函数表达式。规范要求此类函数的名称只能在新函数的范围内使用。规格报价

可以从 FunctionExpression 的 FunctionBody 内部引用 FunctionExpression 中的标识符,以允许函数递归调用自身。但是,与 FunctionDeclaration 不同,FunctionExpression 中的标识符不能被引用,也不影响包含 FunctionExpression 的范围。

另一方面,该表达式的结果是对新函数的引用,可以在任何地方保存和引用。

这里有很多细节:

我读了整本书。

至于好处,另一个是它使它们更容易在调试器中识别。

于 2012-09-06T03:33:33.907 回答
4

用于调用自身的函数。

var x = function y(val){
            if (val){
                console.log(val);
                y(val-1);
            }
        }; 
x(5);
> 3  
> 2  
> 1 
y(3); 
> ReferenceError: y is not defined
于 2012-09-06T03:26:54.103 回答
3

在 JavaScript 中创建函数有两种方法,“函数声明”和“函数表达式”。我相信 Doug Crockford 解释得最好,他指出除非“函数”是给定行上的第一组字符,否则您正在执行函数表达式(而不是声明)。

函数声明是挑剔的生物。当你看到它们时,你会认出它们。它们看起来像这样:

function foo() { /* ... */ }

它们总是被赋予一个名称(这是必需的),并且该名称的局部范围仅限于声明函数的词法上下文。因此,如果您在全局上下文中执行函数声明,则可以通过其名称全局引用该函数。如果您在函数内执行此操作,则只能在该函数内以及在该函数内声明的任何函数内引用该函数的名称。

我认为这种声明函数的方法(很少被评论)最重要的方面是函数初始化被提升到当前词法上下文的顶部。因此,您永远不应该条件中使用函数声明,例如:

//DON'T DO THIS!
if (x) {
    function foo() { return 1; }
} else {
    function foo() { return 2; }
}

foo(); //will always be 2, regardless of the value of x.

函数表达式略有不同。通常,它们被直接分配给一个变量,如下所示:

var foo = function() { /* ... */ };

这与上面的函数声明几乎相同,只是没有提升初始化。因此,您可以执行以下操作:

var foo;
if (x) {
    foo = function() { return 1; };
} else {
    foo = function() { return 2; };
}

foo(); //will be 1 or 2, depending on the truthy-ness of x. 

所以,回到最初的问题。函数表达式也可以有一个名称,尽管它不是必需的,并且它不限于声明函数的上下文(与函数声明一样)。相反,它被限定在函数自己的词法上下文中。这在某些情况下非常有用。我个人最喜欢的是这种模式:

(function foo() {
    //Do something.

    setTimeout(foo, 1000);
}());

foo; //undefined

由于“函数”一词之前的括号,这是一个函数表达式,名称仅在内部范围内。但这没关系,因为我们只需要在内部调用它(通过setTimeout())。结果是该函数将立即执行一次,然后在完成执行后每隔一秒左右重新执行一次。这比使用更安全,setInterval()因为它会等到执行完毕后再重新调度自身,从而防止可能导致错过执行和/或 JavaScript 线程“支配”的重叠。

本质上,命名函数表达式的使用是有限的,但是当您需要它时,它非常强大。

于 2012-09-06T04:23:13.287 回答