2010-09-20 82 views
7

我的直覺是,它的封裝在匿名函數的代碼塊這樣一個好主意:我應該在匿名JavaScript函數中封裝功能塊嗎?

(function() { 
    var aVar; 
    aVar.func = function() { alert('ronk'); }; 
    aVar.mem = 5; 
})(); 

因爲我不會再需要aVar,所以我認爲垃圾收集器會然後刪除aVar當它超出範圍。這是正確的嗎?還是口譯員很聰明,看到我不再使用該變量並立即清理它?是否有任何理由,如風格或可讀性,我應該不是這種方式使用匿名函數?

另外,如果我命名的功能,如:

var operations = function() { 
    var aVar; 
    aVar.func = function() { alert('ronk'); }; 
    aVar.mem = 5; 
}; 
operations(); 

operations那麼必然留下來,直到它超出範圍?或者口譯員能否立即知道何時不再需要?

一個更好的例子

我也想澄清,我沒有必要在談論全球範圍。考慮看起來像

(function() { 

    var date = new Date(); // I want to keep this around indefinitely 

    // And even thought date is private, it will be accessible via this HTML node 
    // to other scripts. 
    document.getElementById('someNode').date = date; 

    // This function is private 
    function someFunction() { 
    var someFuncMember; 
    } 

    // I can still call this because I named it. someFunction remains available. 
    // It has a someFuncMember that is instantiated whenever someFunction is 
    // called, but then goes out of scope and is deleted. 
    someFunction(); 

    // This function is anonymous, and its members should go out of scope and be 
    // deleted 
    (function() { 
    var member; 
    })(); // member is immediately deleted 
    // ...and the function is also deleted, right? Because I never assigned it to a 
    // variable. So for performance, this is preferrable to the someFunction 
    // example as long as I don't need to call the code again. 

})(); 

我的假設和結論在那裏是正確的嗎?每當我不打算重用塊時,我不應該只將它封裝在一個函數中,而是將它封裝在一個匿名函數中,以便該函數沒有引用並在調用它後被刪除,對嗎?

+0

只是好奇,有沒有考慮內存泄漏? – jebberwocky 2010-09-20 17:03:59

回答

4

你說得對,在匿名函數中粘貼變量是避免混淆全局對象的一個​​好習慣。

回答你的後兩個問題:解釋者完全不可能知道一個對象只要有全局可見的引用就不會再被使用。對於所有的翻譯知道,你可以隨時評估一些依賴於window['aVar']window['operation']的代碼。

從本質上講,記住兩點:

  1. 只要對象是各地的,沒有它的插槽將被奇蹟般地沒有你說那麼釋放。
  2. 在全局上下文中聲明的變量是全局對象(客戶端Javascript中的window)的插槽。

這些表示全局變量中的對象在腳本的整個生命週期內持續存在(除非變量被重新分配)。這就是我們聲明匿名函數的原因 - 變量獲取一個新的上下文對象,只要函數完成執行就立即消失。除了提高效率之外,它還可以減少名稱衝突的可能性。儘管如此,你的第二個例子(使用內部匿名函數)可能有點過分熱情。我不擔心在那裏「幫助垃圾收集器」 - 無論如何,GC可能不會在中間運行。擔心會持續存在的事情,而不僅僅是稍微長一些。這些自動執行的匿名函數基本上是自然屬於一組的代碼模塊,因此,一個很好的指導就是考慮是否描述了你正在做的事情。

雖然有理由在匿名函數中使用匿名函數。例如,在這種情況下:

(function() { 
    var bfa = new Array(24 * 1024*1024); 
    var calculation = calculationFor(bfa); 
    $('.resultShowButton').click(function() { 
    var text = "Result is " + eval(calculation); 
    alert(text); 
    }); 
})(); 

這導致了巨大的陣列被點擊的回調使得它永遠不會消失抓獲。你可以通過在自己的函數中隔離數組來避免這種情況。

+0

我理解並同意將此作爲避免混淆全局名稱空間的措施。我認爲我最初的例子沒有充分證明我的問題的範圍。我修改了我的問題以包含更好的示例。 – 2010-09-20 17:52:59

+0

_糾結將永久保持的事情,不只是稍微長於他們本來的時間。 這正是我所期待的!謝謝你的幫助! – 2010-09-21 06:22:04

1

任何添加到全局範圍的內容都會一直保留,直到頁面被卸載(除非您專門刪除它)。

將屬於一起的變量和函數放在本地範圍或對象中,以便儘可能少地添加到全局名稱空間通常是一個好主意。這樣一來,重用代碼就容易多了,因爲您可以在頁面中組合不同的腳本,並將命名衝突的風險降至最低。

+0

沒錯。我同意這一點。我的問題更多的是將匿名函數中的各個代碼塊放在最小範圍內是否合適。一個例子可能是一個對象,我可能通過將它分配爲HTML節點的成員,但其中的一個塊可能只是做它的事情,然後被刪除。我想我的問題更多的是垃圾收集的細節,以及我應該讓我的風格告訴我多少。 – 2010-09-20 17:37:30