由于非常感兴趣, 我查询了很多关于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.