在Javascript定义一个函数一般有如下三种方式:

函数关键字(function)语句:
 

 
function fnMethodName(x){alert(x);}

函数字面量(Function Literals):

 
var fnMethodName = function(x){alert(x);}
 

Function()构造函数:

 
var fnMethodName = new Function('x','alert(x);')


匿名函数,就是没有名字的函数。如:

 
function (){    alert('a function');}
 

但是,上面的代码会报错。firebug提示:function statement requires a name,也就是:函数必须要有个名字。


奇怪的是,如果我用一对()把这个没有名字的函数包起来,就不会报错了。如:

 
(function (){    alert('a function');})
 

(注意包裹函数的()!).虽然这样不会报错,但谁能知道这个函数是否声明成功了呢?是不是因为根本没声明所以才不报错呢?我们这样来测试:让函数自己执行一次:

 
(function (){    alert('a function');}())
 

可以看到,函数执行了,表明函数是存在的。

同样,如果这个时候去掉包裹函数的(),则依然会报前面那个错,函数也执行不了。。。

 
function (){    alert('a function');}()
 


匿名函数

先撇开Google的代码,看一下JavaScript其实是支持这种形式的行数定义的:

 
function(msg){ alert(msg); }("http://www.hzhuti.com/nokia/5236/");
 

这其实是两步:第一步,定义了一个函数,

相当于:

 
var abc = function(msg) { alert(msg);}

第二步,立刻执行它:

 
abc("hello world");

把两个语句拼接在一起,然后去掉abc这个函数的名字,就成了现在的语法形式。

 

封装

另外的一个好处,有可能是为了更好的封装。比如在这个函数里面,有很多的函数定义,比如

 
q(); p(); m(); g(); i()
 

还有大量的变量:

 
var j; var h; var l;

等等。在JavaScript里面没有简单的private这样的定义私有函数或者私有函数的方法。如果调用者可以随心所欲的访问到这些中间的(随时可能变化,甚至移除)成员。对于这么一个开肠破肚,一览无余的对象,从一个API提供者的角度来看(和使用者的角度来看),的确是个挺恐怖的事情。

如果放在一个匿名的函数里面,外界就再也没有办法直接访问到里面的函数了。内部的逻辑被完美的封装了起来。这样一来,这些函数和变量多么的安全!

函数字面量和Function()构造函数的区别


虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。

 
var f = function fact(x) {
  if (x < = 1) return 1;
  else return x*fact(x-1);
};Function()

构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。
Function()构造函数每次执行时都解析函数主体,并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反,函数字面量却不是每次遇到都重新编译的。
用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。

 
var y = "global";
function constructFunction() {
    var y = "local";
    return new Function("return y");  //  无法获取局部变量
}
alert(constructFunction()());  // 输出 "glob

更多详细内容请查看:http://www.111cn.net/wy/js-ajax/42367.htm