将整个 Javascript 文件包装在像“(function(){ ... })()"这样的匿名函数中的目的是什么? [英] What is the purpose of wrapping whole Javascript files in anonymous functions like “(function(){ … })()”?

查看:21
本文介绍了将整个 Javascript 文件包装在像“(function(){ ... })()"这样的匿名函数中的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近阅读了很多 Javascript,我注意到整个文件在要导入的 .js 文件中如下所示.

I have been reading a lot of Javascript lately and I have been noticing that the whole file is wrapped like the following in the .js files to be imported.

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

这样做而不是一组简单的构造函数的原因是什么?

What is the reason for doing this rather than a simple set of constructor functions?

推荐答案

通常是为了命名空间(见下文)并控制成员函数和/或变量的可见性.把它想象成一个对象定义.它的技术名称是立即调用函数表达式 (IIFE).jQuery 插件通常是这样写的.

It's usually to namespace (see later) and control the visibility of member functions and/or variables. Think of it like an object definition. The technical name for it is an Immediately Invoked Function Expression (IIFE). jQuery plugins are usually written like this.

在 Javascript 中,您可以嵌套函数.所以,以下是合法的:

In Javascript, you can nest functions. So, the following is legal:

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

现在可以调用outerFunction(),但是innerFunction()的可见性仅限于outerFunction()的作用域,意思是它是 outerFunction() 私有的.它基本上遵循与 Javascript 中的变量相同的原则:

Now you can call outerFunction(), but the visiblity of innerFunction() is limited to the scope of outerFunction(), meaning it is private to outerFunction(). It basically follows the same principle as variables in 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.

In the above scenario, you can call globalFunction() from anywhere, but you cannot call localFunction1 or localFunction2.

当您编写 (function() { ... })() 时,您正在做的是将第一组括号内的代码作为函数文字(意思是整个对象"实际上是一个函数).之后,您将自调用刚刚定义的函数(最后一个 ()).因此,正如我之前提到的,这样做的主要优点是您可以拥有私有方法/函数和属性:

What you're doing when you write (function() { ... })(), is you're making the code inside the first set of parentheses a function literal (meaning the whole "object" is actually a function). After that, you're self-invoking the function (the final ()) that you just defined. So the major advantage of this as I mentioned before, is that you can have private methods/functions and properties:

(function() {
   var private_var;

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

在第一个示例中,您将按名称显式调用 globalFunction 来运行它.也就是说,您只需执行 globalFunction() 即可运行它.但在上面的例子中,你不仅仅是在定义一个函数;您正在定义一次性调用它.这意味着当您的 JavaScript 文件加载时,它会立即执行.当然,你可以这样做:

In the first example, you would explicitly invoke globalFunction by name to run it. That is, you would just do globalFunction() to run it. But in the above example, you're not just defining a function; you're defining and invoking it in one go. This means that when the your JavaScript file is loaded, it is immediately executed. Of course, you could do:

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

除了一个显着差异外,行为基本相同:使用 IIFE 时避免污染全局范围(因此,这也意味着您无法多次调用该函数,因为它没有名称, 但因为这个函数只在它真的不是问题时才被执行).

The behavior would largely be the same except for one significant difference: you avoid polluting the global scope when you use an IIFE (as a consequence it also means that you cannot invoke the function multiple times since it doesn't have a name, but since this function is only meant to be executed once it really isn't an issue).

IIFE 的妙处在于,您还可以在内部定义事物,并且只将您想要的部分暴露给外部世界(一个命名空间示例,因此您基本上可以创建自己的库/插件):

The neat thing with IIFEs is that you can also define things inside and only expose the parts that you want to the outside world so (an example of namespacing so you can basically create your own library/plugin):

var myPlugin = (function() {
 var private_var;

 function private_function() {
 }

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

现在可以调用myPlugin.public_function1(),但是不能访问private_function()!非常类似于类定义.为了更好地理解这一点,我推荐以下链接以供进一步阅读:

Now you can call myPlugin.public_function1(), but you cannot access private_function()! So pretty similar to a class definition. To understand this better, I recommend the following links for some further reading:

编辑

忘记说了.在最后的 () 中,你可以在里面传递任何你想要的东西.例如,当您创建 jQuery 插件时,您可以像这样传入 jQuery$:

I forgot to mention. In that final (), you can pass anything you want inside. For example, when you create jQuery plugins, you pass in jQuery or $ like so:

(function(jQ) { ... code ... })(jQuery) 

所以你在这里所做的是定义一个函数,它接受一个参数(称为jQ,一个局部变量,并且知道该函数).然后你自己调用函数并传入一个参数(也称为 jQuery,但 this 来自外部世界,是对实际 jQuery 本身的引用).没有迫切需要这样做,但有一些优点:

So what you're doing here is defining a function that takes in one parameter (called jQ, a local variable, and known only to that function). Then you're self-invoking the function and passing in a parameter (also called jQuery, but this one is from the outside world and a reference to the actual jQuery itself). There is no pressing need to do this, but there are some advantages:

  • 您可以重新定义全局参数并为其指定一个在本地范围内有意义的名称.
  • 有一点性能优势,因为在本地范围内查找内容更快,而不必沿着范围链向上走到全局范围内.
  • 压缩(缩小)有好处.

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

Earlier I described how these functions run automatically at startup, but if they run automatically who is passing in the arguments? This technique assumes that all the parameters you need are already defined as global variables. So if jQuery wasn't already defined as a global variable this example would not work. As you might guess, one things jquery.js does during its initialization is define a 'jQuery' global variable, as well as its more famous '$' global variable, which allows this code to work after jQuery has been included.

这篇关于将整个 Javascript 文件包装在像“(function(){ ... })()"这样的匿名函数中的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆