JS自执行函数

js中的立即执行函数

( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法
问题: 为什么会出现上面的两种不一样的写法,上面的写法难道不是简单的就是一个括号包裹匿名函数对象,再在后面加个括号调用函数,最后达到函数定义后立即执行的目的????然后并不是我想的那么简单

1
2
3
4
5
6
除了这种常用的方式:
(function(){ //do something here; })();
(function (){ //do something here;} () );

还有一种方式为:
!function(){ // do something }();

在这里开头要加上 ! 或者 ~ , - 和 +。(note:都是英文符号)
为什么这里要这样子,为什么要在前面加上()、!、+、-、=等运算符????

因为 JavaScript 文法明确规定表达式语句不得以 function 或者 { 为开头(http://es5.github.io/#x12.4)

1
ExpressionStatement → [lookahead ∉ {{, function}] Expression;

好的现在带来更多的困惑了……

首先想要明白这个问题需要弄清函数表达式(function expression)和函数声明(function declaration)的区别:
函数表达式:

函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量 a 来调用。

1
2
3
4
var a = function(){
alert('Function expression');
};
var b = new a();

函数声明:

// 函数声明时必须有函数名

1
2
3
4
function a(){
alert('Function declaration');
}
a();

下面来看一下这段代码:

1
2
3
~function() { 
console.log("hi");
} ();

实际上可以分为两个部分(黑体部分和斜体部分)。黑体部分的匿名函数通过一元操作符变成了函数表达式,因而可以通过在表达式的后面使用 () 来执行 。

因此,执行匿名函数可以通过+,-,!,() 这里的括号也是一种运算符,称为分组运算符
这样的形式来转化为函数表达式,就可以通过表达式的后面使用 () 来执行 。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
( function() {}() );
( function() {} )();
[ function() {}() ];

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

delete function() {}();
typeof function() {}();
void function() {}();
new function() {}();
new function() {};

var f = function() {}();

1, function() {}();
1 ^ function() {}();
1 > function() {}();

下面看一个组错误的的现象:

1
2
3
4
5
function (){console.log("hi")}();
VM354:1 Uncaught SyntaxError: Unexpected token )

function g(){ console.log("hi")}();
VM519:1 Uncaught SyntaxError: Unexpected token )

(1) function (){ }()
期望是立即调用一个匿名函数表达式,结果是进行了函数声明,函数声明必须要有标识符做为函数名称,而这里用()来做为标识符是非法的.

(2) function g(){ }()
期望是立即调用一个具名函数表达式,结果是声明了函数 g。末尾的括号作为分组运算符,必须要提供表达式做为参数。

1
2
function g(){ console.log("hi")}(1);
>>1

所以那些匿名函数附近使用括号或一些一元运算符的惯用法,就是来引导解析器,指明运算符附近是一个表达式。

匿名函数的好处在于:可以减少局部变量,以免污染现有的运行环境。jQuery等库都用到了这样的原理。
另外:通过+,-!这三个符号运行的匿名函数比()运行的匿名函数可以减少一个字符的使用,但是我们通常使用加(),因为其他的操作符可能会带来其他的影响

更多,可以参考 [ECMA-262-3 in detail. Chapter 5. Functions.]

http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses