您的位置:首页 > 其它

立即执行函数: (function(){...})() 与 (function(){...}())

2016-05-09 17:02 183 查看

你需要明白 IIFE 的原理,我简单说一下:

function foo() {...}     // 这是定义,Declaration;定义只是让解释器知道其存在,但是不会运行

foo();                   // 这是语句,Statement;解释器遇到语句是会运行它的。
[/code]

IIFE 并非必须,传统一点可以这么写:

function foo() {...}
foo();
[/code]

那么为什么要 IIFE?

  1. 传统的方法啰嗦,定义和执行分开写;
  2. 传统的方法直接污染全局命名空间(浏览器里的 
    global
     对象,如 
    window

于是,开发者们想找一个可以解决以上问题的写法。那么像下面这么写行不行呢?

function foo(...){}();
[/code]

当然是不能,但是为什么呢?因为 

function foo(...){}
 这个部分只是一个声明,对于解释器来说,就好像你写了一个字符串 
"function foo(...){}"
,它需要使用解析函数,比如 
eval()
 来执行它才可以。所以把 
()
 直接放在声明后面是不会执行,这是错误的语法。

如何把它变得正确?说起来也简单,只要把 声明 变成 表达式(Expression) 就可以了。

实际上转变表达式的办法还是很多的,最常见的办法是把函数声明用一对 

()
 包裹起来,于是就变成了:

(function foo() {...})    // 这里是故意换行,实际上可以和下面的括号连起来
();
[/code]

这就等价于:

var foo = function () {...};    // 这就不是定义,而是表达式了。
foo();
[/code]

但是之前我们说不行的那个写法,其实也可以直接用括号包起来,这也是一种等价的表达式:

(function foo(){...}());
[/code]

所以你问有没有区别?很简单:木有~

另外,刚才说过转变表达式的方式很多,的确还有很多别的写法,比如:

!function foo() {...}();
[/code]

或者

+function foo() {...}();
[/code]

这些都可以。

我个人挺偏爱用 

void
 来转变表达式,因为此关键字不会有返回值。不过这一点真的没有什么要紧的,就当我“龟毛”好了……

void function () {
// 这里是真正需要的代码
}();
[/code]

OK,所谓不去污染全局命名空间,是因为 IIFE 创建了一个新的函数作用域,你真正的业务代码被封装在其中,自然就不会触碰到全局对象了。如果你需要全局对象,那就 pass 给 IIFE:

void function (global) {
// 在这里,global 就是全局对象了
}(this)    // 在浏览器里,this 就是 window 对象
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: