2012-02-19 75 views
0

我正在尝试构建一个类似jQuery.live的函数。 Helper是具有_liveEvent_addEventListener方法的类。 Helper._addEventListener只是W3C addEventListener的CrossBrowser版本。我是否需要在DOM事件回调中使用闭包?

Helper.prototype._liveEvent = function(type, evt, ofunc) { 
    var elHand = document; 
    type = type.toUpperCase(); 

    this._addEventListener(elHand, evt, function(me) { 
     // Inside here I use the `type` variable. 
     // I don't know why but it works. 

     for (var el = me.srcElement; el.nodeName !== 'HTML'; 
      el = el.parentNode) 
     { 
      if (el.nodeName === type || el.parentNode === null) { 
       break; 
      } 
     } 
     if (el && el.nodeName === type) { 
      ofunc.call(el, me); 
     } 

    }); 
}; 

我使用不同类型的Helper._liveEvent函数运行2次。它工作得很好。我认为,因为type变量设置在_liveEvent的上下文中,所以_addEventListener回调只能看到该变量的最后一个版本。但情况并非如此,它似乎工作正常。

我的问题是:

  • 为什么_addEventListener回调可以看到类型的两个版本?
  • 这是否意味着我的代码正在泄漏内存?

UPDATE

这另一个例子让我明白这更好。但我还不确定我是否有这个想法。

function foo(i) { 
    setTimeout(function() { 
     console.log(i); 
    }, 400); 

} 

// Prints 1, 2, 3 
for (var i = 1; i < 4; i++) { 
    foo(i); 
} 

function bar() { 
    for (var i = 1; i < 4; i++) { 
     setTimeout(function() { 
      console.log(i); 
     }, 400); 
    } 
} 

// Prints 4, 4, 4 
bar(); 
​ 

回答

1
  • 这是因为传递给_addEventListener()匿名功能,elHandtype各有其自身价值的每一个实例创建一个独立的封闭范围。
  • 这取决于你的意思是“泄漏”。每次关闭都会防止它从GC中读取的对象。当没有更多的对象(比如说像你这样的匿名函数)引用它时,闭包就会被GC化。在这个意义上,是的,你有内存泄漏,因为你无法删除添加的侦听器(匿名函数),从而使关联的范围对象符合GC的条件。
+0

我认为这个变量具有正确的范围,因为我多次输入了多次_liveEvent,而不是因为我多次创建了一个匿名函数。 – Eduardo 2012-02-19 16:35:32

+0

这里是一样的东西(注意_“每个都有自己的'elHand'和'type'”_提示多个'_liveEvent()'调用)。通过对'_addEventListener()'的两次连续调用添加的监听器是两个不同的Function对象。 – 2012-02-19 16:40:59

+0

看看我的第二个例子。有超时的那个。 foo和bar都有多个匿名函数,但只有一个可以工作。范围由foo函数参数保存,而不是由创建的匿名函数 – Eduardo 2012-02-19 16:44:47

1

实际上,您已经创建了一个闭包。这就是为什么:

for(var i=0; i<10; i++) { 
    elem.onclick = (function(id) {alert(id);})(i); 
} 

作品 - 调用匿名函数创建一个新的封闭与id设置为i当前值。 (就我个人而言,我喜欢用与我想使用的变量相同的参数来调用该参数,所以我可以将其视为“锁定”该函数的变量值)。

就内存泄漏而言,两个调用不会导致泄漏。如果GC按照我认为的方式工作,它将删除没有指向它们的任何关闭。特别是,当你离开页面时,与该页面相关的任何内存都将被释放。

+0

感谢您的支持。我知道关闭是如何工作的,但是这个具体案例让我怀疑。因为我从不执行匿名函数。 – Eduardo 2012-02-19 16:13:40

相关问题