2012-02-18 42 views
2

這個問題更多的是JavaScript原則。Javascript關閉 - 從全局範圍覆蓋的功能的行爲

function done(){ console.log('done defined with `function done(){ ...`'); } 
var done = function(){ console.log('done defined with `var done = ...`'); } 
done = function(){ console.log('without `var`, just `done = ...`'); } 

如果定義在<script>標籤裏面,他們都會做同樣的事情吧?

但是,如果我把它們放在一個封閉(function(){功能definintion放在這裏}())將所有這三種類型中覆寫全局定義的函數()完成或任何其他()完成被內部定義的函數他們各自的關閉?

如果上面的問題沒有意義,這裏是改寫;

  • 是下面的代碼應該在任何JS運行時做同樣的事情?
  • eval - 任何地方的代碼都可以在上下文或全局範圍內執行該特定代碼?
  • 如何才能setTimeout電話進行配置,以便其「引號」之間的代碼執行中具有特定setTimeout被稱爲範圍內(請參見下面的內部for秒超時)?我的意思是除了定義window.blabla函數並告訴他們在運行後刪除自己以外,還有其他方法嗎?

    function done(d){ console.log('cha cha cha: '+d); } 
    setTimeout(function(){ done(2); }, 3500); 
    
    for(i=0; i<10; i++){ 
        (function(){ 
         done = function(x){ console.log('done #'+i+' sais: '+x); } 
         setTimeout(function(){ done(i*2); },2500); 
         setTimeout(function(){ done(i*2); }.toString()+'(); ',2500); 
        }()); 
    } 
    
+1

不要用你的第二個超時的方法。或者有什麼理由? – Bergi 2012-02-18 04:01:03

回答

1

有關一般行爲最初的問題:

  • var done =function done做basicaly同樣的事情。它們會影響內部作用域中的外部定義,但它們不會在外部作用域上取代它。

  • done =將設置在範圍相應done變量,或者如果這樣的變量不存在,並且該程序不嚴格模式下運行將創建一個全局變量。

  • 在全球層面,任何功能外,var done =done =應該工作一樣,但他們的工作方式不同在IE中,如果您嘗試使用該變量在另一個腳本標籤(堅持var = - 其更好反正)。

對於非常邪惡的setTimeout和eval問題:

  • 是的,我想應該是標準化的這種東西足以處處工作相同。無論如何我仍然會測試它。 (或者你可以使用一個不同的解決方案,給定邪惡的eval是如何)

  • eval在當前範圍內運行代碼(使用深黑魔法來實現)。如果您想在全球範圍內運行代碼,則可以使用new Function

  • 爲了有setTimeout的運行了短路電流範圍字符串中,你可以添加EVAL自己:再次

    var done = function(d){ console.log('outer done', d); }; 
    
    (function(){ 
        var done = function(x){ console.log('inner done', x); }; 
    
        setTimeout(function(){ done(1); }, 200);   //inner done 
        setTimeout('done(2)', 400);      //outer done 
        setTimeout(function(){ eval('done(3)'); }, 600); //inner done 
    }()); 
    
  • ,你爲什麼EVAL-ING在一個定時器的東西呢?這一切聽起來都很邪惡!

+0

答案最全,謝謝。 這不是壞事,儘管我正在用悍馬穿越猴子,告訴猴子在悍馬內部做些事情,爲了將我所有的代碼保存在同一個JS項目中,我必須做一些瘋狂的事情,比如通過JSON傳遞函數。這也是語法高亮的問題。 – 2012-02-18 04:26:48

+0

那麼,在這裏,我生活在與悍馬過猴子是最明顯被認爲是邪惡的:P – hugomg 2012-02-18 04:38:28

+0

爲setvalue與eval你不需要eval你只是將eval內的函數綁定到這是你所在的範圍。 – helly0d 2012-03-30 18:49:09

0

var donedone之間的差異,因爲後者牽連window.done並且可以因此delete d。

語句done = foobar;將覆蓋作用域鏈中的下一個「完成」變量。如果有一個本地var,它會改變,如果是全局的,它會覆蓋那個,如果沒有,它會創建一個新的全局。 所有這些都不會影響其他作用域(閉包)中的任何私有變量。

0

關於您的第一個塊的一個註釋。如果您在第一行中爲函數指定名稱,則該函數名稱將在編譯時解析並在範圍內的任何位置可用。如果您只是將函數分配給變量,那麼該函數(即變量)僅在運行時定義,,甚至後可用,如果您給它的名稱。

例如:

// this is valid 
foo(); 
function foo(){ console.log("foo"); } 

// this throws an error... 
bar(); 
var bar = function(){ console.log("bar"); }; 

// ...and so does this... 
baz(); 
var bat = function baz(){ console.log("bazbat"); }; 

// ...and this! 
baz();