(function(){}())与(function(){})()的区别

直接进入正题。请说出 immediately-invoked function expression(IIFE)的如下两种写法的区别: express

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

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

嘛,从效果上来讲,正如StackOverflow(SO)上的网友说的:“It genuinely doesn’t matter, so do whatever you prefer.”。好吧囧,不要拍砖,其实在语法层面上仍是有区别的,如下配合引用SO上的CMS(这是网友id,不是那啥……)的描述来说讲。 app

首先要明白如下写法是语法错误的: 函数

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

编译器会认为该表达式是函数声明,因为在‘function’与‘()’之间找不到函数名称而抛出语法错误。为了可以实现immediately-invoked,因而有了在讨论的两种写法。 学习

对于第一种写法,经过将函数表达式的调用用括号包起来,使编译器理解括号内的代码是表达式而不是声明,从而可以正确解析: ui

CallExpression
                |         |
       FunctionExpression |
                |         |
                V         V
    (function() {       }());
    ^                      ^
    |--PrimaryExpression --|

对于第二种写法,其实也是经过括号将函数表达式包起来使编译器明白该函数表达式不是声明从而正确编译,而后马上使用‘()’来调用这个函数: code

PrimaryExpression
                |
         FunctionExpression
                |
                V
    (function() {       })();
    ^                      ^
    |--  CallExpression  --|

能够看出,两种写法的关键点就是经过将表达式放在‘()’中,使编译器可以正确识别其为函数表达式而不是声明。因而,其实下面的写法也都是能够的: 对象

-function(){}();
+function(){}();
!function(){}();
...

呃……这些写法确实非常有趣,并且也比本文讨论的两种写法少了一个字符……但存在很大的缺陷。考虑下面的语句: 编译器

var obj = !function() {
    return {};
}();

很显然,无论函数里返回了什么,最后obj变量保存的都是true布尔值。而使用括号包住的方式则能正确返回Object对象。 it

ok,相信看官看到这里应该已经明白IIFE的写法了(若是你说这真是个很无聊的问题……其实我也是这么想XD~重要的是学习的过程啊亲)。那还有一个问题就是,使用哪一种写法是比较推荐的呢?jQuery推荐第一种写法,而老道Crockford则推荐第二种。如下是老道这样推荐的缘由: io

“[...] and again, I’m wrapping the whole function and the invocation in parens. as a sign to the reader that there is something bigger going on than just an assignment of a function. There are some people who will put the golden paren. around the function and not around the whole invocation — that doesn’t make sense to me because what we are trying to tell the user is: ‘Look at the whole thing’, and putting parentheses around just part of it, I think, is counter-productive, so I think the whole thing needs to be wrapped in parens.” — Douglas Crockford.

大意是说:使用括号将函数与调用符一块儿包含起来,是为了告诉读者这是一个总体,而只包含函数表达式的写法对他来讲没有意义。

可是我我的是比较习惯第一种写法的,将函数表达式与调用符经过括号分隔开,在我看来是更清晰的调用。嘛,仁者见仁智者见智,想怎么用就怎么用吧,这个问题上没什么好辩论的:)

最后是给看到文章末尾的人的福利哈哈。偶然看到的函数调用方式:

(a || b) && (a || b)()
// 等价于:
// a ? a() : (b && b());

虽然没想到什么场景下会有这样的调用,但以为想到这个的人真有才…

相关文章
相关标签/搜索