Javascript 什么';命名一个函数(而不是不命名)和创建对它的引用之间的区别是什么?

Javascript 什么';命名一个函数(而不是不命名)和创建对它的引用之间的区别是什么?,javascript,function,variables,anonymous-function,Javascript,Function,Variables,Anonymous Function,在我开始的另一个帖子的评论中,有人说: @是的。试试这个:var foo=function bar(){};console.log(foo);但是请注意,bar只是函数名(这是什么意思,我自己也不太清楚),而不是对它的引用,所以不能通过执行bar()调用它。赋值(甚至命名函数)与声明函数不同。吊装(跳到范围顶部)仅适用于声明,任务将保持原位瓦伦提纳斯6小时前 如果不能使用bar()调用函数名,函数名有什么作用?函数可以调用自身 var x = function y(val){

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

@是的。试试这个:var foo=function bar(){};console.log(foo);但是请注意,bar只是函数名(这是什么意思,我自己也不太清楚),而不是对它的引用,所以不能通过执行bar()调用它。赋值(甚至命名函数)与声明函数不同。吊装(跳到范围顶部)仅适用于声明,任务将保持原位瓦伦提纳斯6小时前


如果不能使用
bar()
调用函数名,函数名有什么作用?

函数可以调用自身

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
您引用的是一个命名函数表达式。规范要求此类函数的名称仅在新函数的范围内可用:

FunctionExpression中的标识符可以从内部引用 FunctionExpression的FunctionBody允许函数调用 它自己是递归的。但是,与函数声明不同 FunctionExpression中的标识符不能从中引用,并且不能引用 不影响包含FunctionExpression的范围

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

这里有很多细节:

我读了整件事


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

有两种方法可以在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
由于单词“function”前面有括号,因此这是一个函数表达式,名称的作用域仅限于内部。但这没关系,因为我们只需要在内部调用它(通过
setTimeout()
)。结果是函数将立即执行一次,然后在完成执行后每隔一秒左右重新执行一次。这比使用
setInterval()
更安全,因为它会等到执行完成后再重新调度自己,从而防止可能导致错过执行和/或“支配”JavaScript线程的重叠


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

您的名称和地址之间有什么区别?除了名称/地址类比之外,您实际上可以在bar()的范围内调用bar(),但在bar()的范围外,您必须使用foo().@HotLicks-这个比喻毫无意义
foo
bar
显然都是这里的名字。他们都指同一个地址。只是其中一个只在新函数的范围内可用。@Iwburk为我回答了这个问题,我认为。非常有趣,也很复杂。好吧,那么它们就不会与其他任何东西冲突了,真的。您可以有:
varx=函数z(v){if(v){console.log(v);z(v-1);};var y=函数z(v){if(v){console.log(v);z(v-1);}
注意这两个函数,它们都在内部标记为
z
。这是一个非常有用的答案。它被接受了,我认为有一种方法可以“赠予”声誉,如果有,我会这么做,但我找不到它。我希望你能成为我的JS老师。如果你写课本,我会买的。你有博客或其他什么吗?@adlwalrus我很感激你的赞扬。我没有博客、书或类似的东西。但我确实建议您查看Doug Crockford的JavaScript讲座(搜索“Crockford on JavaScript”)。它们很棒,是我所知道的关于JavaScript的大部分知识的来源。:-)你读过/你会推荐/好的部分吗?我的一个朋友有它,所以如果我想借的话我可以借。还有,你推荐什么特别的讲座作为一个门户?@lwburk是的,我转到了一家实际上对他们的客户和同事一窍不通的公司。(非专题)