作为前端,我们经常会遇到这种函数写法:
!function() {do something...}()
~function(){do something...}()
这样的写法是什么意思呢?
众所周知,在js中可以这样创建一个匿名函数:
(function(){do something...})()
//或
(function(){do something...}())
匿名函数后面的小括号()是为了让匿名函数立即执行。
那为什么这么写就会报错呢:
function(){alert(1)}() // Uncaught SyntaxError: Unexpected token (
其实很简单,因为function前面没有(或者! ~之类的运算符,js解析器会试图将关键字function解析成函数声明语句,而不是函数定义表达式!
作为组运算符,小括号()会将其内部的表达式当成一个整体,然后返回结果,所以定义一个匿名函数正确的格式就是用小括号将函数体括起来!
同样的! ~ + -等运算符也有同样的效果,这是因为匿名函数也是一种值,这些运算符会将后面的函数体当成一个整体,先对匿名函数进行求值,然后在对结果进行运算!
不过这些运算符虽然能够达到让匿名函数立即执行的目的,但是要小心他们是有副作用的,比如:
~function() {alert(1)}() //-1
+function() {alert(1)}() //NaN
-function() {alert(1)}() //NaN
!function() {alert(1)}() //true
!function() {return 1}()//false
~function() {return 1}()//-2
-function() {return false}()//0
-function() {return false}()//0
没错,他们会对函数的返回值进行运算,这样可能会导致最终的结果和你想要的结果不一样!当然,对于那些没有返回值的函数来说,当然是没有什么影响了!
其实无论是括号,还是感叹号,让整个语句合法做的事情只有一件,就是让一个函数声明语句变成了一个表达式。
任何消除函数声明和函数表达式间歧义的方法,都可以被解析器正确识别.
赋值,逻辑,甚至是逗号,各种操作符都可以告诉解析器,这个不是函数声明,它是个函数表达式。并且,对函数一元运算可以算的上是消除歧义最快的方式,感叹号只是其中之一,如果不在乎返回值,~ + - !等都是有用的。