JavaScript 跟你想得不一樣(二)

與其說跟你想得不一樣,還不如說是容易造成誤解吧。

到底 this 是誰?

JavaScript 的 code 寫多了,你一定會碰到 this 這個關鍵字,是某個 object 下的 method 也好,或是 callback function 也好,關於 this 的用法常常會讓人搞混。

以一句簡單的話來說:在 function 裡,this 所代表的就是呼叫這個 function 的東西

以下面這段程式碼為例,onButtonClick 是一個處理按鈕被按下時的 callback function:

var button = document.getElementById('foo');
var onButtonClick = function(evt) {
alert(this);
};

if (button.addEventListener) {
button.addEventListener('click', onButtonClick, false);
} else {
button.attachEvent('onclick', onButtonClick);
}

上面這段 code 分別為了 non-IE 及 IE 瀏覽器不同的註冊 event handler 的寫法來操作,你可以發現,當你在 non-IE 的瀏覽器上執行這段程式碼,當按鈕按下時,訊息視窗應該會跳出有 HTMLInputElement 的訊息,表示呼叫這個 callback function 的物件就是 button,然而,在 IE 底下,你看到的則是 Window。雖然有這樣的不同,但至少有一件事是一致的:this 代表的就是 caller

至於一般的 function,「沒指定的話」都是 window,注意我這裡強調是「沒指定」,所以這也就代表了「可以指定」,以下面這段程式碼為例:

var foo = function(x) {
alert(x);
alert(this);
}
foo('abc');

你應該會看到訊息視窗先顯示 abc,接著就是顯示出 window。但若是變成下面這樣呢?

var foo = function() {
alert(arguments[0]);
alert(this.name);
}
var bar = { name: 'bar' };
foo.apply(bar, ['abc']);

在呼叫 foo 函式時使用 apply 方法,就可以更換 caller(正確地說是切換 context),而因為用了 apply 方法,函式的參數就要改以陣列傳入。當然,這時候的 this 就變成了 bar.....

簡單地結論就是....要在 function 裡使用 this 一定要很小心啊啊啊~