2012-02-19 34 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

相關問題