JavaScript是一种解释型语言,函数声明会在JavaScript代码加载后、执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释。
在JS中有两种定义函数的方式,
1是:var aaa=function(){...}
2是:function aaa(){...}
var 方式定义的函数,不能先调用函数,后声明,只能先声明函数,然后调用。
function方式定义函数可以先调用,后声明。
var
后者会先于同一语句级的其他语句。
即:
{
}
不会出错,
而
{
}
则会出错。
我们来看一下:
var p=function(){}();
这段代码是什么意思。
看了下面这几个例子后,大家就会一目了然了。
var p = function(){return 'abc';}();
alert(p);//abc
alert(typeof p); //string
var p = function(){return 111;}();
alert(p);//111
alert(typeof p); //number
现在明白了吧,其实就是定义了一个变量,这个变量是后面函数的返回值。
用Javascript 两大特点,也是JS引擎的实现必然导致的:
1) 返回值。在JS引擎中,所有的语法,操作都有返回值,而且通常返回值是它本身或undefined。通常我们可以用"()"操作符,来获取当前句子的返回值(部分操作符不能用,如var)。例如:a=3;其实这行的返回值就是3,所以在a=b=3时,JS引擎就可以正确的执行下去,首先3赋值给b,然后当前的返回值3再赋值给a(而不是大家所认为的,先将3赋值给b,然后再将b赋值给a)。又例如函数var fun=function(){},当JS引擎执行到这行时,会先执行右边,返回值是一个函数的字面量,然后将这个函数字面量赋值给fun。
Jquery也是利用了这个特性(函数return this),所以才有链式调用。我们看个例子:"fontFamily".replace( /([A-Z])/g, "-$1" ).toLowerCase(),没错这里也是利用了返回值,所以这行的结果是:font-family。
2) 闭包。子函数调用父函数的变量(非传参),就是闭包。在JS中,子函数能访问父函数的变量,这时被引用的变量不会释放,而且子函数中能一直持有这个变量的引用。
结合以上两大特点,可以生成一个力量强大的怪胎:
(function(){})();
不知道专业的名称,我叫它为:立即执行匿名函数。
首先在第一对括号内,是一个匿名函数,第二个括号会立即调用这个匿名函数的返回值,也就是匿名函数中的内容被立即执行。
这个怪胎的强大在于,它独立了一个作用域(括号中内容执行完后会被立即回收),内部变量外部无法访问,而它又能通过this保留字,来访问外部变量。
举个例子:
var i=100;
(function(){
var j=1;
this.plus_ij = function(){
j+=i;
alert(j);
}
})();
plus_ij();
plus_ij();
上面的例子中,立即执行匿名函数,可以访问到外部变量i,甚至可以var定义一个i(也不会影响外部的i值)。而且内部变量j形成了一个闭包,不会释放。
上一篇博文中介绍过function fn(){}和var fn=function(){},不过,那是在全局作用域中,如果我们将他们放到立即执行匿名函数中,会发生什么呢?
(function(){
var a = function(){}
function b(){}
this.c = function(){ a(); b(); }
})();
c();
上面的例子,你会发现,无论哪种定义方式,在立即执行匿名函数外,都无法访问到a和b函数。也就是a和b函数成了这个立即执行匿名函数的内部函数,外部无法调用,除了通过这个立即执行匿名函数内部定义的外部函数。