最近,我阅读了很多Javascript,并且注意到整个文件都被包装成如下格式,并导入了.js文件。

(function() {
    ...
    code
    ...
})();

为什么这样做而不是使用一组简单的构造函数呢?

最佳答案

通常是到 namespace (请参阅下文)并控制成员函数和/或变量的可见性。可以将其视为对象定义。它的技术名称是立即调用函数表达式(IIFE)。 jQuery插件通常是这样写的。

在Javascript中,您可以嵌套函数。因此,以下是合法的:

function outerFunction() {
   function innerFunction() {
      // code
   }
}

现在您可以调用outerFunction(),但是innerFunction()的可见性仅限于outerFunction()的范围,这意味着它对outerFunction()是私有(private)的。它基本上遵循与Javascript中的变量相同的原理:
var globalVariable;

function someFunction() {
   var localVariable;
}

相应地:
function globalFunction() {

   var localFunction1 = function() {
       //I'm anonymous! But localFunction1 is a reference to me!
   };

   function localFunction2() {
      //I'm named!
   }
}

在上述情况下,您可以在任何地方调用globalFunction(),但是不能调用localFunction1localFunction2

当您编写(function() { ... })()时,您正在做的是使第一组括号内的代码成为函数文字(意味着整个“对象”实际上是一个函数)。之后,您将自动调用刚刚定义的函数(最后的())。因此,正如我之前提到的,它的主要优点是您可以拥有私有(private)方法/函数和属性:
(function() {
   var private_var;

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

在第一个示例中,您将按名称显式调用globalFunction来运行它。也就是说,您只需要执行globalFunction()即可运行它。但是在上面的示例中,您不仅定义了一个函数,还定义了一个函数。您可以一口气定义和调用它。这意味着当您的JavaScript文件被加载时,将立即执行它。当然,您可以这样做:
function globalFunction() {
    // code
}
globalFunction();

除了一个显着的区别外,该行为基本上是相同的:避免使用IIFE时污染全局范围(因此,这也意味着您不能多次调用该函数,因为它没有名称,但是由于该功能仅在确实不是问题后才可以执行)。

IIFE的整洁之处在于,您还可以在内部定义事物,并且只向外界公开想要的部分(例如,命名空间的示例,这样您就可以基本上创建自己的库/插件):
var myPlugin = (function() {
 var private_var;

 function private_function() {
 }

 return {
    public_function1: function() {
    },
    public_function2: function() {
    }
 }
})()

现在您可以调用myPlugin.public_function1(),但是无法访问private_function()!因此非常类似于类定义。为了更好地理解这一点,我建议以下链接以供进一步阅读:
  • Namespacing your Javascript
  • Private members in Javascript (by Douglas Crockford)

  • 编辑

    我忘了提。在最后的()中,您可以在内部传递任何内容。例如,当您创建jQuery插件时,您像这样传递jQuery$:
    (function(jQ) { ... code ... })(jQuery)
    

    因此,您在这里要做的是定义一个带有一个参数的函数(称为jQ,一个局部变量,并且仅对该函数已知)。然后,您将自动调用该函数并传入一个参数(也称为jQuery,但这是来自外部世界,它是对实际jQuery本身的引用)。这样做并没有紧迫的需求,但是有一些优点:
  • 您可以重新定义全局参数,并为其指定在本地范围内有意义的名称。
  • 有一点性能优势,因为它可以更快地在本地范围内查找内容,而不必将范围链带入全局范围。
  • 压缩(最小化)有很多好处。

  • 早先,我描述了这些函数如何在启动时自动运行,但是如果它们自动运行,谁传入参数?该技术假定您所需的所有参数均已定义为全局变量。因此,如果尚未将jQuery定义为全局变量,则此示例将不起作用。您可能会猜到,jquery.js在其初始化期间所做的一件事是定义了一个'jQuery'全局变量,以及它更为著名的'$'全局变量,这使该代码在包含jQuery后可以工作。

    10-05 20:30
    查看更多