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之旅真是學到不少東西啊!
沒有留言:
張貼留言