5.1.12 闭包

很有用,却经常被忽略。
有一件需要注意的事情,闭包会保持一个指向它封闭作用域的指针,所以在给DOM元素附加闭包时,很可能会产生循环引用,进一步的消耗内存,比如下面的代码:

function foo(element, a, b) {
  element.onclick = function() { /* uses a and b */ };
}

即便这个闭包函数内部并没有使用 element,可它还是保持了对 element, a 和 b 的引用,而 element 也保持了对这闭包函数的引用,就导致了循环引用,无法被GC回收。如果遇到了这种情况,可以将代码优化一下:

function foo(element, a, b) {
  element.onclick = bar(a, b);
}

function bar(a, b) {
  return function() { /* uses a and b */ }
}

译者注:由于IE9之前的版本对JScript对象和COM对象使用不同的垃圾收集例程,因此闭包在IE的这些版本中会导致如上问题。这个匿名函数作为element元素事件处理程序,形成闭包的状态就会保存对父层函数内活动对象的引用,只要匿名函数存在,element的引用数至少也是1,因此它所占用的内存就永远不会被回收。注意,闭包会引用包含函数的整个活动对象,即使闭包不直接引用element,包含函数的活动对象中也仍然会保存一个引用。因此,有必要把使用完的element变量设置为null,解除对DOM对象的引用,确保正常回收其占用的内存。(取自《Javascript高级程序设计》184P)