【问题标题】:Advanced JavaScript: Why is this function wrapped in parentheses? [duplicate]高级 JavaScript:为什么这个函数用括号括起来? [复制]
【发布时间】:2012-02-21 15:43:22
【问题描述】:

可能重复:
What is the (function() { } )() construct in JavaScript?

我遇到了这段 JavaScript 代码,但我不知道该怎么做。为什么我在运行此代码时得到“1”? (1) 的这个奇怪的小附录是什么?为什么函数用括号括起来?

(function(x){
    delete x;
    return x;
})(1);

【问题讨论】:

    标签: javascript function syntax parentheses iife


    【解决方案1】:

    表示你创建了一个匿名函数,并使用参数1调用它。

    和下面的一样:

    function foo(x) {
        delete x;
        return x;
    }
    foo(1);
    

    【讨论】:

    • 我会使用var foo = function(){} 避免混淆函数语句和函数表达式。
    • @missingno 他们是一样的。
    【解决方案2】:

    仍然返回 1 的原因是 delete 关键字用于删除对象的属性。其余的就像其他人评论的那样,括号中的任何内容都作为函数执行,第二组括号是传递给该块的参数。

    这里是MDN reference for deleteMDN reference for closures,它们还讨论了匿名函数。

    【讨论】:

      【解决方案3】:

      人们通常称这些“立即调用函数表达式”或“自执行函数”。

      这样做的重点是在该函数内部声明的变量不会泄漏到外部。

      【讨论】:

        【解决方案4】:

        这里发生了一些事情。首先是immediately invoked function expression (IIFE) 模式:

        (function() {
          // Some code
        })();
        

        这提供了一种在自己的范围内执行一些 JavaScript 代码的方法。它通常用于使函数内创建的任何变量都不会影响全局范围。你可以改用这个:

        function foo() {
          // Some code
        }
        foo();
        

        但这需要给函数命名,这并不总是必要的。使用命名函数还意味着在将来某个时间点可能会再次调用该函数,这可能是不可取的。通过以这种方式使用匿名函数,您可以确保它只执行一次。

        此语法无效:

        function() {
          // Some code
        }();
        

        因为您必须将函数包装在括号中才能使其解析为表达式。更多信息在这里:http://benalman.com/news/2010/11/immediately-invoked-function-expression/

        所以快速回顾一下 IIFE 模式:

        (function() {
          // Some code
        })();
        

        允许立即执行“某些代码”,就好像它只是内联编写一样,但也在其自己的范围内,以免影响全局命名空间(因此可能会干扰其他脚本或被其他脚本干扰) .

        您可以像传递普通函数一样向函数传递参数,例如,

        (function(x) {
          // Some code
        })(1);
        

        因此,我们将值“1”作为第一个参数传递给函数,该函数将其作为局部范围的变量接收,命名为 x。

        其次,你有函数代码本身的胆量:

        delete x;
        return x;
        

        删除操作符将删除对象的属性。它不会删除变量。所以;

        var foo = {'bar':4, 'baz':5};
        delete foo.bar;
        console.log(foo);
        

        结果被记录:

        {'baz':5}
        

        然而,

        var foo = 4;
        delete foo;
        console.log(foo);
        

        将记录值 4,因为 foo 是一个变量而不是一个属性,所以它不能被删除。

        由于自动全局变量的工作方式,许多人认为 delete 可以删除变量。如果你给一个变量赋值而不先声明它,它实际上并不会成为一个变量,而是全局对象上的一个属性:

        bar = 4; // Note the lack of 'var'. Bad practice! Don't ever do this!
        delete bar;
        console.log(bar); // Error - bar is not defined.
        

        这一次删除有效,因为您删除的不是变量,而是全局对象上的一个属性。实际上,前面的 sn-p 等价于:

        window.bar = 4;
        delete window.bar;
        console.log(window.bar);
        

        现在您可以看到它与 foo 对象示例而不是 foo 变量示例的相似之处。

        【讨论】:

        • 很好的解释。另外,作为旁注,我看到 Douglas Crockford 在一次演讲中提到他更喜欢 (function() {}());为了清晰起见,有效地将整个 IIFE 包裹在括号中 - 更具表现力。
        • 与 wiki 链接相比,括号包裹了整个内容,有什么不同吗?
        • 所以在(function(x){ delete x; return x; })(1);delete x 没有任何效果,对吧?因为x 是一个变量,而不是一个属性。因此delete x 没有任何效果吧?
        • @Utku 是的,完全正确
        猜你喜欢
        • 2011-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-21
        • 2020-11-15
        • 1970-01-01
        相关资源
        最近更新 更多