一、什么是匿名函数?
在Javascript定义一个函数一般有如下三种方式:
代码如下 | 复制代码 |
1.函数关键字(function)语句: function fnMethodName(x){alert(x);} 2.函数字面量(Function Literals): var fnMethodName = function(x){alert(x);} 3.Function()构造函数: var fnMethodName = new Function('x','alert(x);') |
上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数。
匿名函数的创建
第一种方式:就是上面所讲的定义square函数,这也是最常用的方式之一。
第二种方式:
代码如下 | 复制代码 |
(function(x, y){ alert(x + y); })(2, 3); |
这里创建了一个匿名函数(在第一个括号内),第二个括号用于调用该匿名函数,并传入参数。
二、函数字面量和Function()构造函数的区别
1.虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。
代码如下 | 复制代码 |
var f = function fact(x) { if (x < = 1) return 1; else return x*fact(x-1); }; |
2.Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。
3.Function()构造函数每次执行时都解析函数主体,并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反,函数字面量却不是每次遇到都重新编译的。
4.用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。
代码如下 | 复制代码 |
var y = "global"; function constructFunction() { var y = "local"; return new Function("return y"); // 无法获取局部变量 } alert(constructFunction()()); // 输出 "global" |
和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多,所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别,虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug,但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数
举例
匿名函数最大的用途是创建闭包(这是JavaScript语言的特性之一),并且还可以构建命名空间,以减少全局变量的使用。
示例三:
代码如下 | 复制代码 |
var oEvent = {}; (function(){ var addEvent = function(){ /*代码的实现省略了*/ }; function removeEvent(){} oEvent.addEvent = addEvent; |
在这段代码中函数addEvent和removeEvent都是局部变量,但我们可以通过全局变量oEvent使用它,这就大大减少了全局变量的使用,增强了网页的安全性。我们要想使用此段代码:oEvent.addEvent(document.getElementById('box') ,
代码如下 | 复制代码 |
'click' , function(){}); |
示例四:
代码如下 | 复制代码 |
var rainman = (function(x , y){ return x + y; })(2 , 3); /** * 也可以写成下面的形式,因为第一个括号只是帮助我们阅读,但是不推荐使用下面这种书写格式。 * var rainman = function(x , y){ * return x + y; * }(2 , 3); */ |
在这里我们创建了一个变量rainman,并通过直接调用匿名函数初始化为5,这种小技巧有时十分实用。
示例五:
代码如下 | 复制代码 |
var outer = null; (function(){ outer(); //2 |
这段代码中的变量one是一个局部变量(因为它被定义在一个函数之内),因此外部是不可以访问的。但是这里我们创建了inner函数,inner函数是可以访问变量one的;又将全局变量outer引用了inner,所以三次调用outer会弹出递增的结果。