由于非常感兴趣, 我查询了很多关于IIFE (immediately-invoked function expression)的东西, 如下:

那么为什么不写一篇关于它的文章呢? ;-)

首先,它有一系列不同的东西。从头开始:

作用域

JavaScript有function 作用域, 所以它被用在必须私有作用域的地方。举个例子:

Simple.

它的工作原理

一个普通的函数是这样的:

我们可以调用它的范围和我们提供的作用域没有关系。“IIFE”被创造的原因是它们是立即执行表达式,这意味着他们一创建就马上被执行,当然我们不能再次执行它们。 如下:

这里的秘密武器是这个, (还记得上面分配了一个变量的例子吗?):

如果没有额外的小括号,他们就不能工作:

虽然有一些技巧可以强制让javascript让它工作,如下使用! 字符:

当然还有下面的变体:

但是我不会使用他们.

查看 Disassembling JavaScript’s IIFE Syntax 这是一篇详细介绍IIFE语法和它的变体的文章。

参数

现在我们知道它是怎么工作了,我们可以往IIFE中传参:

这个的工作原理是什么? 注意, 最后的 (window); 是函数的调用, 并且我们传入了一个window 对象。它通过这个传入到函数的变量,这个变量我们也命名为window 。 你可以认为这个是没有意义的,但是现在我们使用window 更好. 那么我们还能做什么? 我们可以传入更多的东西, 让我们传入一个document 对象:

局部变量的调用比全局变量更快, 当然这是在超大规模的情况下,一般情况我们不会感觉到速度的影响 - 但是如果我们用全局变量很多也是值得考虑的。

什么是 undefined?

在ECMAScript 3, undefined是变量. 意味着它的值可以被定义,比如 undefined = true; 在 ECMAScript 5使用严格遵守模式('use strict';) 这个赋值会报错.:

下面是可以得:

压缩

压缩我们的变量是IIFE模式真正实用的地方。局部变量的名字可以在它们传入函数中进行改变,所以我们如下调用:

变为:

想象下,所有的你引入的类库里面的window 和 document 很好的压缩。 如下面的jquery类库的调用:

这意味着你不用使用 jQuery.noConflict(); 任何 $ 都会执行jquery. 学习这个对于变量的作用域会对你帮助很大。一个好的压缩工具会把undefined压缩为c。undefined 的命名是无关紧要的,我们只是需要用它来判断一个对象是否有值或者有没有定值而已

非浏览器全局环境

比如Node.js, 浏览器不在是全局对象,我们会使用IIFE让他在跨环境运行:

在浏览器中,this 指向 window 对象, 所以我们不需要传入 window, 我们可以使用this来缩短. 我喜欢使用root来命名它,如果在非浏览器环境也合适

。 如果你对普通的解决方案感兴趣 这里是一个UMD包装:

在浏览器, root.MYMODULE = factory(); 是我们的IIFE模块, 其他情况(如 Node.js) 它会调用 module.exports 或者当 typeof define === 'function' && define.amd为true 则调用requireJS。当然这个另外一个故事了, 我强烈推荐你看这篇文章 UMD repo.

05-11 13:26