詭異的JavaScript Closure

來源:互聯網
上載者:User

出來混,遲早要還。今天寫JavaScript代碼,才知道一個迴圈裡的 函數共用同一閉包 三個閉套件共用一個變數。比如下面的代碼是錯的,不能正確報告每個事件對應的描述:

var div = document.getElementById("testDiv");
var events = {onclick: "clicked", onchange: "changed",  onmouseover: "mouse over"}; 

for(var e in events){
   div[e] = function(){
      alert(events[e]);
   };
}

試一下就知道。不管激發events列表裡的哪坨事件,alert彈出的視窗裡總是"mouse over"。

不明白JavaScript為什麼這樣處理迴圈和閉包的關係。哪位老大指點一下? 更新:隨便猜一下。JavaScript的Closure環境由靜態句法結構確定。也就是說,代碼一旦寫成,我們就知道函數的自由變數同哪些環境裡的變數綁定。這樣說來,上面的迴圈只申明了一個變數p和一個內建函式,從靜態句法結構來看,我們的確只有一個環境。因此,雖然運行時同一個內函數被調用多次,建立了多個閉包,這些閉包指向的都是同一個環境裡的同一個變數。這樣同JavaScript規定的閉包語義一致。

陽春版的修改辦法是利用函數定義建立新閉包,符合業內名言:任何電腦問題都能通過多加一層抽象解決。:-) Crockford Douglas 把多加的這層函數叫做因子函數(factor function)。

var div = document.getElementById("testDiv");
var events = {onclick: "clicked", onchange: "changed",  onmouseover: "mouse over"}; 

for(var e in events){
   div[e] = function(e){
       return function(){
           alert(events[e]);
       };
   }(e);
}

當然,如果到處建立因子函數,就繁瑣了。所以還是Dojo風格的調用來得清爽:

dojo.lang.forEach(events, function(e){
    alert(e);
});

明眼老大們自然可以看出這是函數編程的風格。其實JavaScript本就是採用C語言句法的簡化版LISP,異常靈活。如果我們注意利用高端函數(加上閉包),便可像搭建積木那樣“拼裝”我們的程式,使代碼變得乾淨利落。Dojo架構裡實現了各式函數編程常用函數,比如map, reduce, filter, find, hitch, curry, 非常方便。再加上prototype chain, 對inspection的強大支援(光arguments.callee就讓俺愛不釋手了),以及call, apply, eval這三個超級函數,在JavaScript裡寫出功能完善的DSL也變得相對容易。 就算不搗騰DSL,JavaScript也有無數妙用。比如Dojo裡處理事件的代碼實現了AOP風格的建議功能,讓我們隨意操縱處理事件的時機,輕鬆截取任意事件的參數,哪怕是普通JavaScript函數調用的參數。而實現這些功能的代碼並不複雜。

從Dojo的實現也可以看出學習多種編程範式的重要性。Dojo裡支援函數編程,物件導向編程,Ruby風格的mixin, AOP風格的事件處理等從不同語言借鑒來的功能。如果Dojo的主程Alex Russell只懂JavaScript,就算他能倒背EMCAScript規範,恐怕也寫不出Dojo。要享受編程,避免一件本來很美好的事變成體力活,功夫永遠在詩外。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.