首先贴一段这样的代码
//正确的代码var foo=function(){ //函数内容 }; foo();
对于这段代码大家都很熟悉,创建一个函数表达式并且立即执行。接下来,我们试着去把这段代码简化,变成一个立即执行函数表达式。
//错误的代码function(){ //函数内容 }()
这段代码与上面代码的区别就是把foo省略了,直接替换成function,但是很明显这样做是不行的,js会给我们报出一个错误。
为什么这样会报错呢?其实原因很简单,函数声明以function关键字开始,同时函数声明还有一个很重要的要求,便是function后面的函数名称functionName不能省略
,而此处的函数名称被省略掉了,所以自然也就出错,那么我们可以怎么改呢?在后面加一个functionName函数名称不就行了吗,好的,让我们来试一下
//错误的代码 function foo(){ //函数内容 }()
实际上,就算在后面加上了函数名称这段代码还是无法正常执行的,js会给我们弹出一个错误“SyntaxError : Unexpected token”,这个错误是什么意思呢?我自己试着在js中只写了一个(),
然后执行,发现也会弹出错误,所以,我怀疑上面的代码是被解析成了这样
//错误的代码 function foo(){ //函数内容 }; ();
就是说js内部把function函数声明和最后的执行括号分开解析了,而由于后面的()里面没有表达式,所以js会弹出错误,无法正常执行。那么当我们试图在后面加入相关表达式是否就能解决这个问题呢?
//错误的代码 function foo(){ //函数内容 }(1)
这时,我们在后面加了“1”,这时,代码确实不报错了(注意:不报错误并不代表函数就是成功执行了),然并卵,因为这个时候function里面的函数内容并没有执行,也就是说我们刚开始的目的:
//正确的代码 var foo=function(){ //函数内容 }; foo();
把这段代码优化并没有成功,所以这个时候,我们试着去换另一种思路来试一下。既然函数声明无法立即执行,那么我们是否可以试一下把函数声明转换成函数表达式然后试图去立即调用呢?
说到这里,我们就要扯一下函数表达式与函数声明的转换。
function foo(){} //这很明显是一个函数声明 var foo=function(){} //这也很明显是一个函数表达式 //重点来了 !function foo(){} //这是一个函数表达式 (function foo(){}) //这也是一个函数表达式
第一个和第二个例子是很容易理解的,但是对于第三四个可能就不是那么容易理解了。为什么最后两个会是函数表达式呢?
就js的解析器而言,如果一条语句以function关键字开始,那么解析器就会把它当作函数声明。所以呢,如果我们在function关键字前面加其它元素,就可以把函数声明转换成函数表达式。
所以
!function foo(){} //前面加了一个!操作符,所以解析成函数表达式。 (function foo(){}) //加了一个()分组操作符,最终也解析为函数表达式。
那么,我们再说回之前的问题,对于刚开始的这段错误代码
//错误的代码 function(){ //函数内容 }()
我们试图把它变成函数表达式而不是函数声明
//这是正确的演示 (function(){ //函数内容 })()
事实证明,在function前面加了一个()分组操作符之后确实成功了,这段代码的执行效果与全文刚开始的地方贴出的代码执行效果是一样的,
而这段代码也是我们平时经常使用的一段代码,创建匿名立即执行函数,以保证全局变量不被污染。
其实除了上面的那种方式,还有一种类似的方法也是可以实现相同效果
//正确的演示 (function(){ //函数内容 }())
而这两种方法也是有区别的,至于有什么区别大家可以自己去查阅一下,本文不再讲述,最后希望可以帮到需要的人。