QPhome# 青浦之家论坛

QQ登录

只需一步,快速开始

2122

积分

13

好友

374

主题
1
发表于 2007-4-18 21:12:48 | 查看: 2408| 回复: 1
出来混,迟早要还。今天写JavaScript代码,才知道一个循环里的函数共享同一闭包。比如下面的代码是错的,不能正确报告每个事件对应的描述:
[color=#0000ff]var[/color][color=#000000] div [/color][color=#000000]=[/color][color=#000000] document.getElementById([/color][color=#000000]"[/color][color=#000000]testDiv[/color][color=#000000]"[/color][color=#000000]);
[/color][color=#0000ff]var[/color][color=#000000] events [/color][color=#000000]=[/color][color=#000000] {onclick: [/color][color=#000000]"[/color][color=#000000]clicked[/color][color=#000000]"[/color][color=#000000], onchange: [/color][color=#000000]"[/color][color=#000000]changed[/color][color=#000000]"[/color][color=#000000],  onmouseover: [/color][color=#000000]"[/color][color=#000000]mouse over[/color][color=#000000]"[/color][color=#000000]};

[/color][color=#0000ff]for[/color][color=#000000](e [/color][color=#0000ff]in[/color][color=#000000] events){
   div[e] [/color][color=#000000]=[/color][color=#000000] [/color][color=#0000ff]function[/color][color=#000000](){
      alert(events[e]);
   };
}[/color]

试一下就知道。不管激发events列表里的哪坨事件,alert弹出的窗口里总是"mouse over"。
不明白JavaScript为什么这样处理循环和闭包的关系。哪位老大指点一下?
阳春版的修改办法是利用函数定义创建新闭包,符合业内名言:任何计算机问题都能通过多加一层抽象解决。:-) Crockford Douglas 把多加的这层函数叫做因子函数(factor function)。
[color=#0000ff]var[/color][color=#000000] div [/color][color=#000000]=[/color][color=#000000] document.getElementById([/color][color=#000000]"[/color][color=#000000]testDiv[/color][color=#000000]"[/color][color=#000000]);
[/color][color=#0000ff]var[/color][color=#000000] events [/color][color=#000000]=[/color][color=#000000] {onclick: [/color][color=#000000]"[/color][color=#000000]clicked[/color][color=#000000]"[/color][color=#000000], onchange: [/color][color=#000000]"[/color][color=#000000]changed[/color][color=#000000]"[/color][color=#000000],  onmouseover: [/color][color=#000000]"[/color][color=#000000]mouse over[/color][color=#000000]"[/color][color=#000000]};

[/color][color=#0000ff]for[/color][color=#000000](e [/color][color=#0000ff]in[/color][color=#000000] events){
   div[e] [/color][color=#000000]=[/color][color=#000000] [/color][color=#0000ff]function[/color][color=#000000](e){
       [/color][color=#0000ff]return[/color][color=#000000] [/color][color=#0000ff]function[/color][color=#000000](){
           alert(events[e]);
       };
   }(e);
}[/color]

当然,如果到处创建因子函数,就繁琐了。所以还是Dojo风格的调用来得清爽:
[color=#000000]dojo.lang.forEach(events, [/color][color=#0000ff]function[/color][color=#000000](e){
    alert(e);
});[/color]

明眼老大们自然可以看出这是函数编程的风格。其实JavaScript本就是采用C语言句法的简化版LISP,异常灵活。如果我们注意利用高端函数(加上闭包),便可像搭建积木那样“拼装”我们的程序,使代码变得干净利落。Dojo框架里实现了各式函数编程常用函数,比如map, reduce, filter, find, hitch, curry, 非常方便。再加上prototype chain, 对inspection的强大支持(光arguments.caller, arguments.callee就让俺爱不释手了),以及call, apply, eval这三个超级函数,在JavaScript里写出功能完善的DSL也变得相对容易。 就算不捣腾DSL,JavaScript也有无数妙用。比如Dojo里处理事件的代码实现了AOP风格的建议功能,让我们随意操纵处理事件的时机,轻松截取任意事件的参数,哪怕是普通JavaScript函数调用的参数。而实现这些功能的代码并不复杂。
从Dojo的实现也可以看出学习多种编程范式的重要性。Dojo里支持函数编程,面向对象编程,Ruby风格的mixin, AOP风格的事件处理等从不同语言借鉴来的功能。如果Dojo的主程Alex Russell只懂JavaScript,就算他能倒背EMCAScript规范,恐怕也写不出Dojo。要享受编程,避免一件本来很美好的事变成体力活,功夫永远在诗外。
分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
转发到微博

收藏回复 只看该作者 道具 举报

2
发表于 2007-4-24 10:12:13
dddddddddddddddddddd

回复 只看该作者 道具 举报

您需要登录后才可以回帖 登录 | 注册

回顶部