Javascript的匿名函数

一、什么是匿名函数?

在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,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数

二、函数字面量和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: The Definitive Guide, 5th Edition》的Functions那章。

三、匿名函数的代码模式

昨天hedger wang在他的blog介绍了几种匿名函数的代码模式

错误模式:其无法工作,浏览器会报语法错。

function(){
  alert(1);
}();
  1. 函数字面量:首先声明一个函数对象,然后执行它。
    (function(){
      alert(1);
    } ) ( );
  2. 优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。
    ( function(){
      alert(2);
    } ( ) );
  3. Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数。
    void function(){
      alert(3);
    }()

这三种方式是等同的,hedger wang因为个人原因比较喜欢第3种,而在实际应用中我看到的和使用的都是第1种。

四、匿名函数的应用

  1. 《Javascript的一种模块模式》中的第一句话就是“全局变量是魔鬼”。配合var关键字,匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。这在给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。实际上,YUI以及其相应的范例中大量使用匿名函数,其他的Javascript库中也不乏大量使用。
  2. Javascript的函数式编程(functional programming)的基石。具体请看《用函数式编程技术编写优美的 JavaScript》《函数式JavaScript编程指南》

标签:, ,

作者:秦歌,时间:2008-05-07 1:14,归纳于:Javascript & DOM & AJAX,订阅:RSS 2.0,引用:Trackback

有评论 38 条,发表一条新评论 »

llinzzi说:2008-05-07 9:18 #1

路过,学习一下

天空诚说:2008-05-07 13:39 #2

不错,很有收获

cssrain说:2008-05-07 22:08 #3

文章写得不错哦,,

火星人路人甲说:2008-05-08 14:12 #4

不太明白 优先表达式 ,“Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数”这个可以举例说明吗?

秦歌说:2008-05-08 23:16 #5

5*(3+4)=35。()强制了加法先进行。

Robin说:2008-05-13 9:41 #6

cssrain 哈哈~ 看来确实是酒香不怕巷子深呀.

strongwillow说:2008-07-04 17:58 #7

不错,学习了

andy65007说:2008-07-11 1:24 #8

分析的很深入

JavaScript的陷阱 @ 随网之舞说:2008-10-27 0:28 #9

[...] 这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

tyc说:2008-11-05 11:10 #10

看了你的文章后获益匪浅,这个知识点,一直困扰着,现在明了多了!期待你写更好的文章,帮助学习js的人!

wuqing说:2008-11-30 21:55 #11

狗屁不通。。。。。。。。。。。。。。

Javascript的匿名函数 | 完全COPY说:2008-12-19 11:31 #12

[...] Javascript的匿名函数 Javascript的匿名函数 [...]

Fengdesudu说:2009-01-06 13:28 #13

不错

Javascript的匿名函数 | 可可虫说:2009-03-01 16:04 #14

[...] Javascript的匿名函数 [...]

桑拿院的小伙子说:2009-05-07 11:53 #15

受益匪浅,以前我对 new Function()模式 很不熟悉,而有时候接触的代码中,作者老是用 这种形式,现在才知道了,是为了不受作用域的束缚才这么写的。

匿名说:2009-06-06 22:30 #16

js中有命名函数吗?

不及格程序员- 八神

JavaScript的陷阱 « RIA sky说:2009-06-22 15:48 #17

[...] 这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

sf说:2009-08-17 16:35 #18

太怪的写法,一般人很难掌握的,

Supersha说:2009-12-07 18:22 #19

void function(){
alert(3);
}()
这种方式第一次见,开眼界了。^_^

使用匿名函数得体的话,将会是非常方便的,比如:
(function(arr){
var i=0;c=null;
while(c===arr[i++]){
window["is"+c]=function(obj){
return toString.call(obj)===”[object "+c+"]“;
}
}
})(["Object","Function","Array","String","Number"]);

simaopig说:2009-12-09 18:24 #20

经典,学习了。呵呵。

Silentash-默尘 » Javascript 匿名函数及其代码模式原理说:2009-12-27 3:00 #21

[...] 上面这段代码会抛出语法错误,这究竟是为什么呢?带着这个问题我们来看看秦歌给出的解答:1.函数字面量:首先声明一个函数对象,然后执行它。2.优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。3.void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数。 好吧,先不管解答是否正确,我们把这些放到一边,再来看看函数声明的语法和函数表达式的语法说明:一、函数声明: [...]

soog说:2010-01-08 23:14 #22

经典 学习了。。。。

匿名说:2010-01-21 11:41 #23

var f = function fact(x) {

个人觉得这种写法只是jscript的一个bug,根本毫无用处,

Physure.com » [转]Javascript的匿名函数说:2010-02-06 0:15 #24

[...] http://dancewithnet.com/ [...]

Physure.com » [转]JavaScript的陷阱说:2010-02-06 0:17 #25

[...]   这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

Physure.com » [转]JavaScript的陷阱说:2010-02-06 0:17 #26

[...]   这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

匿名说:2010-05-11 21:07 #27

rrtr

js匿名函数 - 林部落说:2010-07-07 13:44 #28

[...] http://dancewithnet.com/2008/05/07/javascript-anonymous-function/ [...]

JavaScript的陷阱 « Koubei UED说:2010-07-08 20:55 #29

[...] 这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

Javascript的匿名函数 - 搞基百科 - 有码的百科全书说:2010-08-28 16:18 #30

[...] 原文 http://dancewithnet.com/2008/05/07/javascript-anonymous-function/ [...]

匿名说:2010-09-16 14:17 #31

不错,很想知道优先级的匿名函数模式和第一个模式有什么区别

JavaScript的一些博客链接 | Wang Jun's Blog说:2010-12-09 17:23 #32

[...] 暂无评论 网上牛人真多。。。。1.javascript匿名函数。http://dancewithnet.com/2008/05/07/javascript-anonymous-function/,文章后面的链接也是非常不错的 [...]

JavaScript的陷阱 « 梦寻千里 – WEB前端开发者说:2011-04-15 17:34 #33

[...] 这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》。YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》。 [...]

忠云说:2011-06-13 19:17 #34

http://hi.baidu.com/geyangshun/blog/item/74248fb14cb6bf44082302d5.html

忠云说:2011-06-13 19:18 #35

你讲的稍微有点问题,http://hi.baidu.com/geyangshun/blog/item/74248fb14cb6bf44082302d5.html
这位同学已经详细的说了!

前端体验说:2011-09-25 11:27 #36

总结的很透彻,受教了

匿名说:2011-10-11 16:09 #37

我一直都还没弄明白javascript这种办法的好处是什么?类似C的内联?区别于编译型的解释型语言为了满足(不是充要而是必要条件的满足--如网页的异步加载中可能会出现的情形)即时执行而设计的一种机制?没弄明白。如果没有实质的好处,弄这一花腿不就是画蛇添足吗。静候大佬们注解。

理解Javascript 匿名函数 | See Me After 9说:2011-10-23 23:41 #38

[...] 秦歌 的 Javascript的匿名函数 [...]

发表一条评论

您可以在下面评论内容中使用下列XHTML标签:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


回到页眉