(function(){})()构造如何工作以及人们为什么使用它?

Tom*_*man 78 javascript

(function() {})()并且它的jQuery特定表亲(function($) {})(jQuery)一直在Javascript代码中弹出.

这些结构如何工作,它们解决了哪些问题?

举例赞赏

Seb*_*Seb 73

随着JavaScript框架的日益普及,该$标志被用于许多不同的场合.因此,为了减轻可能的冲突,您可以使用这些结构:

(function ($){
  // Your code using $ here.
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

具体来说,这是一个匿名函数声明,它立即执行,将主jQuery对象作为参数传递.在该函数内部,您可以使用它$来引用该对象,而不必担心其他框架也在范围内.

  • 它在技术上是一个函数表达式(!声明).[IIFE](http://benalman.com/news/2010/11/immediately-invoked-function-expression/) (5认同)
  • 简短而有意义的答案.+1! (4认同)

Dan*_*ant 40

这是一种用于限制变量范围的技术; 这是防止变量污染全局命名空间的唯一方法.

var bar = 1; // bar is now part of the global namespace
alert(bar);

(function () {
   var foo = 1; // foo has function scope
   alert(foo); 
   // code to be executed goes here
})();
Run Code Online (Sandbox Code Playgroud)

  • ......并且仍然让它们对您的代码具有"全局性". (7认同)

Eva*_*oli 19

1)它定义了一个匿名函数并立即执行它.

2)通常这样做是为了不用不需要的代码污染全局命名空间.

3)你需要从中公开一些方法,在里面声明的任何东西都是"私有的",例如:

MyLib = (function(){
    // other private stuff here
    return {
        init: function(){
        }
    };

})();
Run Code Online (Sandbox Code Playgroud)

或者,或者:

MyLib = {};
(function({
    MyLib.foo = function(){
    }
}));
Run Code Online (Sandbox Code Playgroud)

关键是,有很多方法可以使用它,但结果保持不变.


Guf*_*ffa 9

它只是一个立即调用的匿名函数.您可以先创建该函数,然后调用它,您将获得相同的效果:

(function(){ ... })();
Run Code Online (Sandbox Code Playgroud)

作为:

temp = function(){ ... };
temp();
Run Code Online (Sandbox Code Playgroud)

您也可以使用命名函数执行相同操作:

function temp() { ... }
temp();
Run Code Online (Sandbox Code Playgroud)

您调用jQuery特定的代码只是在您使用jQuery对象的意义上.它只是一个带有参数的匿名函数,可以立即调用.

你可以分两步完成同样的事情,你可以使用你喜欢的任何参数:

temp = function(answer){ ... };
temp(42);
Run Code Online (Sandbox Code Playgroud)

这解决的问题是它为函数中的代码创建了一个闭包.您可以在其中声明变量而不会污染全局命名空间,从而降低使用一个脚本和另一个脚本时发生冲突的风险.

在jQuery的特定情况下,您在兼容模式下使用它,它不会将名称$声明为jQuery的别名.通过将jQuery对象发送到闭包并命名参数$,您仍然可以使用与没有兼容模式相同的语法.


Ewa*_*odd 7

这里解释说,您的第一个构造为变量提供了范围.

变量的范围是javascript中的函数级别.这与您在C#或Java等语言中的习惯不同,其中变量的作用域为块.这意味着如果在循环或if语句中声明变量,它将可用于整个函数.

如果您发现自己需要在函数内显式定义变量,则可以使用匿名函数来执行此操作.您实际上可以创建一个匿名函数,然后立即执行它,其中的所有变量将作用于匿名函数:

(function() {
  var myProperty = "hello world";
  alert(myProperty);
})();
alert(typeof(myProperty)); // undefined
Run Code Online (Sandbox Code Playgroud)


tva*_*son 6

执行此操作的另一个原因是消除$您正在使用哪个框架的运算符的任何混淆.例如,要强制执行jQuery,您可以执行以下操作:

;(function($){
   ... your jQuery code here...
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

通过将$运算符作为参数传入并在jQuery上调用它,$即使您加载了其他框架,函数中的运算符也会锁定到jQuery.


Gre*_*ill 5

此构造的另一个用途是"捕获"将在闭包中使用的局部变量的值.例如:

for (var i = 0; i < 3; i++) {
    $("#button"+i).click(function() {
        alert(i);
    });
}
Run Code Online (Sandbox Code Playgroud)

上面的代码将使所有三个按钮弹出"3".另一方面:

for (var i = 0; i < 3; i++) {
    (function(i) {
        $("#button"+i).click(function() {
            alert(i);
        });
    })(i);
}
Run Code Online (Sandbox Code Playgroud)

这将使三个按钮按预期弹出"0","1"和"2".

这样做的原因是闭包保持对其封闭堆栈框架的引用,该框架保存其变量的当前值.如果这些变量在闭包执行之前发生变化,那么闭包只会看到最新的值,而不会看到创建闭包时的值.通过将闭包创建包装在另一个函数中,如上面的第二个示例所示,变量的当前值i保存在匿名函数的堆栈框架中.