了解立即表达式前我们来回顾下函数表达式吧。定义函数的方式有两种:一种是函数声明,另一种就是函数表达式。我们最熟悉的函数表达式肯定是匿名函数赋值给变量。
var method = function(){
console.log("this is a function")
}
method() //this is a function
函数表达式不是我们的主角,在以上代码中,匿名函数被赋值给了变量method,通过变量名+()就执行了函数,这样说你是不是发现了什么?变量名后面的()就是立即执行表达式,函数表达式+()就能立即执行该函数(划重点)。对此我是这样理解的(才疏学浅,理解错误还请告知)
不管是函数申明还是函数表达式,都有一个函数名,这个函数名是函数在内存中的地址,浏览器要执行函数代码需靠它寻址,而()的功能就是告知浏览器,我要执行这个函数,麻烦你通过它的地址找到它并执行代码。匿名函数并没有将自己的地址告诉给任何变量,所以一般要调用匿名函数需要立即调用表达式。
大家再看看以下代码
function(){
// write something here
}()
这里浏览器会报错!!!
为什么呢?明明匿名函数可以将自己赋值给变量,那匿名函数不就相当于会返回自己的地址么?其实不然,在var method = function(){ }
中, JavaScript 将 function 关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。要将函数声明转换成函数表达式,只要像下面这样给它加上一对圆括号即可
(function(){
// write something here
})()
代码中的一对括号就是将函数申明转换为函数表达式,相同的功能还有!,+,-,=,这也解释了为什么method是函数表达式了,因为 = 将匿名函数转化为了函数表达式,值得注意的是在匿名函数赋值时不能使用+,-,!,应为他们会将函数表达式直接进行类型转换——NaN或false。
(function(a){
console.log(a); //firebug输出1234,使用()运算符
}(1234));
!function(a){
console.log(a); //firebug输出12345,使用!运算符
}(12345);
+function(a){
console.log(a); //firebug输出123456,使用+运算符
}(123456);
-function(a){
console.log(a); //firebug输出1234567,使用-运算符
}(1234567);
那函数(匿名函数)到底会不会返回值呢?我试了下用console.log()输出函数,结果如下:
console.log会直接打印函数,匿名函数亦同
那直接将带名的函数赋值会怎么样呢?
将已经申明的函数赋值给变量,就会发现函数申明中出现的函数名,此处为d会无效,但是查询函数的名字,又是d。
(Firefox、 Safari、 Chrome 和 Opera 都给函数定义了一个非标准的 name 属性,通过这个属性可以访问到给函数指定的名字。这个属性的值永远等于跟在 function 关键字后面的标识符。
//只在 Firefox、 Safari、 Chrome 和 Opera 有效
alert(functionName.name); //"functionName")
在以上代码中我们可以发现,函数申明的方式进行函数表达式赋值,被申明的函数名(例如函数d)会无效化,也就是函数表达式会直接将其视为匿名函数,但是并不会更改函数的.name
属性
总结
- 函数表达式:变量名 = 匿名函数 >>> m = function(){}
- 立即执行表达式 >>> (function())() 或 (function()())
- 匿名函数转换为函数表达式:+,-,!,=,()
- 已经有名字的函数(有名函数)和匿名函数,直接打印会输出函数本身及其代码
- 直接将函数申明赋值给变量会将函数地址所有权转让给变量,而函数名会失去函数表达式的功能
- 函数一旦被命名,函数名.name的值就固定了,不会改变(匿名函数属于未命名状态)