一堆小闭包 vs 一个大闭包

3

我有一个谷歌地图,在不同的事物上添加了事件监听器。例如,我有一个点对象,对于这个对象,我一直在如下添加事件:

google.maps.event.addListener(this.marker, 'click', (function(point) {
    return function(event) {
        alert(point.index);
    }})(this));

我有很多这些事件(例如“click”,“rightclick”,“doubleclick”等)。

当我添加事件时,我会专门为当前点创建一个闭包。但是,我很想做的是:

var point = this;

google.maps.event.addListener(this.marker, 'click', function(event) {
    alert(point.index);
});

我一直在回避这个问题,原因有两个。
第一个是因为我见过比我更懂Javascript的人使用“独立”的闭包,所以我想他们肯定有好的理由。
第二个原因是(我对Javascript的解释一无所知),我想知道创建一个大闭包是否会捕获所有其他我不会在事件函数中使用的变量(例如'var color')。这会导致性能问题吗?
谢谢您的帮助!
2个回答

1

只要您的观点不改变,这样做应该没有问题。因此,按照您的第二个示例进行操作就可以了。

var point = this;

google.maps.event.addListener(this.marker, 'click', function(event) {
  alert(point.index);
});

通常情况下,当您的点绑定到更改并且您需要它处于不同状态时(例如在循环中),您会执行事件处理函数的另一个闭包:
for(var i = 0, len = points.length; i < len; i++) {
  google.maps.event.addListener(points[i].marker, 'click', (function(point) {
    return function(event) {
      alert(point.index);
    }
  })(points[i]));
}

如果在我的例子中我们没有使用闭包,在事件触发的那一刻,我们将会引用到数组points的最后一个元素。

1

你的两个示例都创建了一个闭包,这个闭包涵盖了一个叫做 point 的东西。在第一个示例中,point 是外部匿名函数的一个参数,在第二个示例中,point 是一个本地变量。但无论哪种情况,它最终都会被一个匿名函数所封闭。

创建一个接受一个命名参数并立即调用带有一个参数的匿名函数只是在特定范围内将一个值绑定到名称的一种方式。

(function(x) { 
    // now x has the value
})(getValue());

或者:

var x = getValue();
// now x has the value

区别在于使用函数可以确保 x 存在于其自己的命名空间中,不会与封闭作用域中的任何其他 x 合并。也就是说,这种方式的价值在于可维护性,而非执行速度。

哪种方法更好?唯一的方法是在多个浏览器上进行测试-它们都有自己的执行引擎。

看起来创建越多匿名函数,就会发生更多小的分配。因此,您的第二个示例,其匿名函数较少,可能表现更好。但这纯粹是没有根据的猜测,需要在您关心的每个浏览器中进行测试。


谢谢回复。然而,假设在我的第二段代码中,在“var point = this”之前有“var lotsofmemory = new Array(10000);”。当“lotsofmemory”不再需要时,它是否仍会浪费空间,因为它与匿名函数一起被封闭?(我知道像Chrome这样的浏览器可能启发式地优化这种事情,但IE呢?) - Nick
如果您编写一个重复执行该操作的脚本,并将匿名函数存储在列表中,那么您应该能够测量其效果(如果有的话)。 - Daniel Earwicker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接