回调函数网络上一大堆,这里举个实际的例子:

<script src="../javascripts/jquery-1.4.2.js"></script>

<script language="javascript">

  $(document).ready(init);

  function init(){
    console.log("....init");
    var sd = new Date();
    $('.list').each( function(){
      this.onclick= function(){
        console.log("you click,haha");
        process(sd);
      };
    });
  };

  function process(youDate){
    console.log("I got it:" + youDate);
  }

</script>

<div id="nav">
  <div>11</div>
  <div>22</div>
  <div>33</div>
</div>

逻辑很简单:当页面加载时注册回调函数,当点击div时激发回调函数。这里注册和激发是异步的。

注意回调函数可以访问上一级的成员变量sd(或许在FP中称为运行上下文),这个跟java的observer模式中的内部类可以访问容器类的this指针一样,这就是说当你点击div时,原来已经产生的时间变量sd还在,这样打印出来的时间都是旧的时间。这是closure的灵活强大的地方(《JavaScript: The Good Parts》里面说,“使用闭包来进行信息掩藏的方式,它是另一个减少有效全局污染的方法”。真知灼见啊!,否则又要使用大量的全局变量),但是跟Java一样,这里由于引用的关系可能会出现垃圾回收的困难,java用弱引用来处理这个问题。这篇文章Memory leak patterns in JavaScript有描述,里面提到了circular references,大概意思是javascript对象引用了DOM对象,而DOM对象反过来又引用了javascript对象。上面代码改成:

$('.list').click( function(){
  console.log("you click,haha");
  process(s);
});

可能更好点,因为this.onclick处可能隐含了DOM对象到Javascript对象的引用,而在$(‘.list’)处又有javascript obj到dom obj的引用。这个我没有求证,毕竟这种内存泄漏在浏览器上关掉当前页后就应该不存在了,不会引起很明显的问题,知道有这个事就好了。