[轉帖]淺談js中的this指針

JavaScript最有魔力的關鍵字之一就是this。但很不幸它並不容易駕馭。我會先來解釋如何在事件句柄中使用this。稍後我會提及一些關於this的其他用法。

擁有者(Owner)

看這樣一個問題,在doSomething函數中,this指代什麼?
function doSomething() {
   this.style.color = "#cc0000";
}

在JavaScript中this永遠指向函數執行時的擁有者(owner), 更確切地說,是指向了這個方法所屬的對象。 當我們在頁面中定義了doSomething()函數, 他的擁有者就是window object (or global object) of JavaScript。 然而onclick 屬性則是屬於它對應的html element。

------------ window --------------------------------------
|                                          / \           |
|                                           |            |
|                                          this          |
|   ----------------                                     |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          --------------------                          |
|          | onclick property |                          |
|          --------------------                          |
|                                                        |
-----------------------------------------------------------
如果我們沒有更改擁有者而直接執行doSomething函數,那麼它將試圖更改window的style對象而最終報錯。

複製引用(Copying)

要小心對待下面這種複製一個函數爲一個html元素事件處理函數的用法,這時doSomething函數就被這個html元素所擁有
element.onclick = doSomething;

所以當函數執行時將會改變html元素的color。

------------ window --------------------------------------
|                                                        |
|                                                        |
|                                                        |
|   ----------------                                     |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------                       |
|                                                        |
----------------------------------------------------------

這種技巧當然適用於把函數複製到多個不同元素的事件處理函數上。每次執行,this都指向不同的元素。

------------ window --------------------------------------
|                                                        |
|                                                        |
|                                                        |
|   ----------------                                     |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------          |            |
|                                           |            |
|   -----------------------                 |            |
|   | another HTML element| <-- this        |            |
|   -----------------------     |           |            |
|               |               |           |            |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------                       |
|                                                        |
----------------------------------------------------------

引用調用(Referring)

然而當你使用如下的行內註冊事件方式

<element οnclick="doSomething()">

你沒有複製這個函數! Instead, you refer to it, 這之間的不同非常嚴重。 元素的onclick 屬性沒有代替爲實際的函數,而是僅僅調用了函數:

doSomething();

所以當執行 doSomething()this再次global window object,並且會返回錯誤信息.

------------ window --------------------------------------
|                                          / \           |
|                                           |            |
|                                          this          |
|   ----------------                        |            |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------         / \           |
|          | go to doSomething() |          |            |
|          | and execute it      | ---- reference to     |
|          -----------------------       function        |
|                                                        |
----------------------------------------------------------

The difference

如果你想執行函數時this指向正確的html元素,你必須確保 this 被寫入到了元素的 onclick 屬性。所以

element.onclick = doSomething;
alert(element.onclick)

you get

function doSomething()
{
 this.style.color = '#cc0000';
}

As you can see, the this keyword is present in the onclick method. Therefore it refers to the HTML element.

如果你這樣做了:

<element οnclick="doSomething()">
alert(element.onclick)

you get

function onclick()
{
 doSomething()
}

這樣僅僅調用了函數doSomething()This現在不在onclick方法裏面,所以它不會指向正確的html元素。

Examples - copying

this is written into the onclick method in the following cases:

element.onclick = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element οnclick="this.style.color = '#cc0000';">

Examples - referring

In the following cases this refers to the window:

element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element οnclick="doSomething()">

要注意微軟的實現attachEvent(). The main drawback of the Microsoft event registration model is thatattachEvent() creates a reference to the function and does not copy it. Therefore it is sometimes impossible to know which HTML currently handles the event.

Combination

When using inline event registration you can also send this to the function so that you can still use it:

<element οnclick="doSomething(this)">

function doSomething(obj) {
 // this is present in the event handler and is sent to the function
 // obj now refers to the HTML element, so we can do
 obj.style.color = '#cc0000';
}
轉自:http://zmike86.blog.163.com/blog/static/17186042120121202122793/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章