js中的立即执行函数
( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法
问题: 为什么会出现上面的两种不一样的写法,上面的写法难道不是简单的就是一个括号包裹匿名函数对象,再在后面加个括号调用函数,最后达到函数定义后立即执行的目的????然后并不是我想的那么简单
1 | 除了这种常用的方式: |
在这里开头要加上 ! 或者 ~ , - 和 +。(note:都是英文符号)
为什么这里要这样子,为什么要在前面加上()、!、+、-、=等运算符????
因为 JavaScript 文法明确规定表达式语句不得以 function 或者 { 为开头(http://es5.github.io/#x12.4)
1 | ExpressionStatement → [lookahead ∉ {{, function}] Expression; |
好的现在带来更多的困惑了……
首先想要明白这个问题需要弄清函数表达式(function expression)和函数声明(function declaration)的区别:
函数表达式:
函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量 a 来调用。
1 | var a = function(){ |
函数声明:
// 函数声明时必须有函数名
1 | function 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
5function (){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
2function 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