在SF上看到这样一个问题,我以为问得很好,因此弄成文章收集了。浏览器
没有区别。函数
你须要明白 IIFE 的原理,我简单说一下:this
function foo() {...} // 这是定义,Declaration;定义只是让解释器知道其存在,可是不会运行。 foo(); // 这是语句,Statement;解释器遇到语句是会运行它的。
IIFE 并不是必须,传统一点能够这么写:code
function foo() {...} foo();
那么为何要 IIFE?对象
传统的方法啰嗦,定义和执行分开写;作用域
传统的方法直接污染全局命名空间(浏览器里的 global 对象,如 window)开发
因而,开发者们想找一个能够解决以上问题的写法。那么像下面这么写行不行呢?字符串
function foo(...){}();
固然是不能,可是为何呢?由于 function foo(...){}
这个部分只是一个声明,对于解释器来讲,就好像你写了一个字符串 "function foo(...){}"
,它须要使用解析函数,好比eval()
来执行它才能够。因此把 ()
直接放在声明后面是不会执行,这是错误的语法。io
如何把它变得正确?提及来也简单,只要把 声明 变成 表达式(Expression) 就能够了。function
实际上转变表达式的办法仍是不少的,最多见的办法是把函数声明用一对 () 包裹起来,因而就变成了:
(function foo() {...}) // 这里是故意换行,实际上能够和下面的括号连起来 ();
这就等价于:
var foo = function () {...}; // 这就不是定义,而是表达式了。 foo();
可是以前咱们说不行的那个写法,其实也能够直接用括号包起来,这也是一种等价的表达式:
(function foo(){...}());
因此答案是:木有区别~
另外,刚才说过转变表达式的方式不少,的确还有不少别的写法,好比:
!function foo() {...}();
或者
+function foo() {...}();
这些均可以。
我我的挺偏心用 void 来转变表达式,由于此关键字不会有返回值。不过这一点真的没有什么要紧的,就当我“龟毛”好了……
void function () { // 这里是真正须要的代码 }();
OK,所谓不去污染全局命名空间,是由于 IIFE 建立了一个新的函数做用域,你真正的业务代码被封装在其中,天然就不会触碰到全局对象了。若是你须要全局对象,那就 pass 给 IIFE:
void function (global) { // 在这里,global 就是全局对象了 }(this) // 在浏览器里,this 就是 window 对象