星期五, 2月 01, 2013

[JavaScript][OO] this object memo

  最近在跟Josehpj (啊嗚)討論 JavaScript的 Object Oriented 時候討論到 this 物件, 啊嗚有提到一段話,我直接引用如下:
JavaScript 在語言本身、模擬物件導向的開發中,this 都是很清楚的代表一個 instance。

把 this 搞複雜的原因,其實是瀏覽器特有的 DOM API。
像是 DOM Event、或像是 window.XMLHttpRequest 這樣的全域方法。
this 在對應的處理函式中都不會是所預期 instance。
這也是為什麼在 Y.on 或 Y.io 都有提供設定 context 的參數。
或者得自己去使用 call 或 apply 取執行 Handler、讓 Handler 正確處理。

如果今天開發的是沒有瀏覽器的 JavaScript,例如 Node.js,
this 通常是不會造成太大的困擾的 :)

  再說程式之前我先名詞解釋一下: "context", 何謂 context, 中譯最接近的意思就是上下文, 前後文. 常常我們看到一個句子會不太懂他的由來的時候, 若知道他的上下文, 我們很快就可以知道他的涵義.

  這邏輯推到變數也是一樣, 看到一個變數我們可能不太知道意義的話, 若能知道他的上下文, 大概就比較知道他到底是誰使用他了, 而下面例子當中所舉的的 this, 就是上面說的 context(上下文). 以程式舉例, 我後面有標 (1) (2) (3) 註解:
 on: {
   viewload: function () { 
      api = this;
      api.get(node).
         one('form').on('submit', _handleSubmit, api); 
      // (1).api is the context
    }
 }
 _handleSubmit = function (event) {
   var _api = this; //(2) this is api from (1) context
   _api.get(node).all('input');

   _enableForm.call(_api, arg1, arg2); 
   //(3.1) this _api is context
   _enableForm.apply(_api, [arg1, arg2]); 
   //(3.2) this _api is context
 }
  上述的範例說當一個模組在頁面載入完成要執行的 function call (on viewload). 當按下 Submit 按鈕送出之後相對應的handler (_handleSubmit) 會處理相對應的動作.

submit是 event的名字,  _handleSubmit是 callback funciton, 而第三個參數就是context了.

  而 (3.1) , (3.2)則是 JavaScript常拿來執行函式的方式.

  下方例子則是特別情況, 假設我有個物件 _api有 confirm的方法( 類似於 JavaScript的 confirm), 傳入message, 以及 callback. 而此時callback有需要 _api當其 context.則此時可以使用YUI的 Y.bind.


_api.confirm(message, callback); 
//callback will need _api as context
_api.confirm(message, Y.bind(callback. _api)); 
//callback will need _api as context

這次的 JavaScript this之旅真是學到不少東西啊!


沒有留言: