Javascript闭包(回调函数)的问题
回调函数网络上一大堆,这里举个实际的例子:
<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的引用。这个我没有求证,毕竟这种内存泄漏在浏览器上关掉当前页后就应该不存在了,不会引起很明显的问题,知道有这个事就好了。