首页 文章

命名函数(而不是离开它)和创建引用之间的区别是什么?

提问于
浏览
2

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

@adlwalrus是的 . 试试这个:var foo = function bar(){};的console.log(FOO);但请注意,bar只是函数名称(这意味着我不确定自己)并且不是对它的引用,所以你不能通过执行bar()来调用它 . 分配(甚至命名函数)与声明函数不同 . 吊装(撞到顶部的顶部)仅适用于声明,分配将保持不变 . - valentinas 6小时前

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

3 回答

  • 4

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

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

    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线程的"domination" .

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

  • 3

    用于调用自身的功能 .

    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
    
  • 4

    你指的是一个命名函数表达式 . 规范要求此类函数的名称仅在新函数的范围内可用 . Spec quote

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

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

    这里有很多细节:

    我读了整篇文章 .

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

相关问题