2008-10-28 39 views
3

函數的放置是否影響範圍內閉包的性能?如果是這樣,放置這些功能的最佳位置在哪裏?如果不是的話,隱含的關聯是否足夠理由將邏輯上的某個功能置於另一個地方?javascript關閉和函數放置

例如,如果不依賴於localState的價值,確實的事實,localState是訪問從必須爲的執行時間,內存使用的影響,等等。?

(function(){ 
    var localState; 

    function foo(){ 
     // code 
    } 

    function bar(){ 
     // code 
     return localState; 
    } 
})(); 

換句話說,這是一個更好的選擇,如果是的話,爲什麼?

(function(){ 
    function foo(){ 
     // code 
    } 

    var localState; 

    function bar(){ 
     // code 
     return localState; 
    } 
})(); 

Darius Bacon曾建議below的是,上述兩個樣品是相同的,因爲localState可以從塊內的任何地方訪問。但是,foo以下示例在塊外部定義可能是不同的情況。你怎麼看?

function foo(){ 
    // code 
} 

(function(){ 

    var localState; 

    function bar(){ 
     // code 
     foo(); 
     return localState; 
    } 
})(); 

回答

3

在Javascript中的每個函數是一個閉包。只有當變量被函數引用時纔會解析變量值。例如,在這個例子中函數y捕捉即使X不是用y直接引用的x的值:

var x = 3; 
function y() eval("x"); 
y(); 
3 
1

var或function聲明的範圍是它顯示的整個塊,而不管聲明在塊中的哪個位置;所以它會影響效率會令人驚訝。

也就是說,它不應該的問題「函數foo()」是之前還是之後「VAR localState」這個區塊內。它可以也罷「函數foo()」是該塊或包圍一個(如果它可以被提升到一個更高的範圍,因爲它不使用任何局部變量);這取決於你的Javascript編譯器的細節。

2

,我不認爲會有任何性能開銷,因爲Java腳本不使用函數棧的概念。它支持詞法範圍。在關閉調用中執行相同的狀態。在附註中,在你的例子中,你似乎沒有執行任何語句!

+0

你說得對!我試圖暗示用「」// code「」註釋來執行一些執行,但顯然不是很清楚。感謝您的回答。 – brad 2008-10-28 17:24:07

5

兩個那些片段是等價的,因爲他們都在你創建匿名函數(下同)環境中定義。我想你無論如何都可以從foo訪問localState

這就是說......如果在創建的環境中存在大量變量,那麼foo的執行時間可能會受到影響,因爲變量查找可能需要更長的時間。如果在函數中不再使用大量變量,則您定義foofoo也不需要它們,那麼foo將導致它們不被垃圾收集,因此這也可能是問題。

+0

事實上,一看就知道JS其實不關過未使用的變量,試試這個:(函數(){VAR一個= 1;復位功能(X){的eval(X)}})()(「警報(一) 「)顯然,內部函數沒有提及`a`,但它是可用的。 – ephemient 2008-10-28 20:12:57

+0

相反,在Perl中,子{我的$ a = 1;子{EVAL $ _ [0]}} - >()( '打印$ a')中,不打印任何東西,但子{我的$ a = 1時;子{$一個; EVAL $ _ [0]}} - >()( '$ A')的作用:Perl的關心該變量是否被引用,以確定它是否被關閉了。 – ephemient 2008-10-28 20:18:22

5

狗,我希望聲明的順序會是這樣的JavaScript解釋器將抽象掉。無論如何,如果存在性能差異,那麼將其作爲過早優化弊端的海報孩子是非常小的。

0

在你的例子的差異將沒有真正的問題。即使foo在全球範圍內,你也不會有問題。

然而,這是非常有用的記住,如果你使用爲變量分配功能的風格來聲明你的函數中,他們聲明會變得非常有問題的順序。

對於一個更好的主意,請嘗試以下兩個例子:

CheckOne(); 
function CheckOne() { 
    alert('check...check one.'); 
} 

CheckTwo(); 
var CheckTwo = function() { 
    alert('check...check two.'); 
}; 

第二和第一之間唯一的區別是他們使用申報功能的風格。第二個生成參考錯誤。

乾杯。