關於javascript中this關鍵字(翻譯+自我理解)

來源:互聯網
上載者:User

下文有大概70%的內容出自http://www.quirksmode.org/js/this.html,另外30%是我自己對它的理解和感想。希望能對有需要的人一點協助。。。

首先,先看一個很典型的關於this關鍵字題目:複製代碼 代碼如下:var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());

這裡也不賣關子了,執行結果為:hong
稍微改下代碼: 複製代碼 代碼如下:var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
var that = this;
return function(){
return that.name;
};
}
}
alert(obj.getName()());

執行結果為:ru
執行結果為:ru

關於出現這種結果的原因,下面會細細討論。
【函數的擁有者】
要解釋this,要先說這個概念。在JavaScript裡,this始終指向我們當前正在執行的函數的“擁有者”。更為確切的說:是指向把這個函數作為方法的對象。
這句話怎麼理解,我們可以看看下面的例子: 複製代碼 代碼如下:/* -- test1 -- */
function test1 () {
this.title = 'me';
alert(window['title']);
alert(this === window); //true
}
test1();

執行結果為:me, true
在上例中,this是指向window對象的。並把window這個對象的title屬性寫為'me',因為test1是個頂級函數,所以它的擁有者是window對象,或者說它是window對象的一個方法。這個應該不難理解。比如上面調用test1()時,也可以寫成 window.test1();這樣的明了了。

  接下來,我們建一個div,並把test1作為方法賦給div的onclick屬性: 複製代碼 代碼如下:<div id="o" style="width:50px;height:50px;border:4px solid #333">me!</div>
<script type="text/javascript">
/* -- test1 -- */
function test1 () {
this.title = 'me';
alert(window['title']);
alert(this === window);
}
var o = document.getElementById('o');
o.onclick = test1;
</script>

點擊div結果為:undefined, false; 同時我們用firebug可以看到‘me'這個屬性值其實是被賦給了id為‘o'的這個HtmlObject

顯而易見,此時this指向了這個div,也就是說,test1()的擁有者變成了div這個HtmlObject,或者說它變成了div的onclick方法來調用。這種情況應該還是容易理解的。
下面我們接著改代碼,就改一個地方: 複製代碼 代碼如下:o.onclick = test1(); // 注意:這裡加了個括弧

把上面代碼的最後一句改成這樣後,點擊div啟動並執行結果為:me, true
變成了和第一種情況一樣了,this指向了window。有人會納悶,覺得沒什麼區別,其實是有區別的。這裡涉及到函數的copy和refer的問題。

  【函數的Copy】
  如果通過 複製代碼 代碼如下:o.onclick = test1;

這樣的方式的話,其實是把test1() 這個函數Copy給了對象 o 的 onclick 屬性。因此test1的擁有者變成了 o 這個對象。
  如果通過 複製代碼 代碼如下:o.onclick = test1();

這樣的方式的話,本質上是指當擷取到點擊事件的handle時,指引它去執行test1()函數。注意是指引去執行而不是賦給它去執行。test1()的擁有者沒變,還是window.

  【函數的Refer】
  同上,我們通過inline的方式把調用寫到html裡來調用的話,還是refer的方式 複製代碼 代碼如下:<div id="o" style="width:50px;height:50px;border:4px solid #333" onclick="test1()">me!</div>

點擊div執行結果還是表示this指向window。
  【函數copy的例子】 複製代碼 代碼如下:element.onclick = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element onclick="this.style.color = '#cc0000';">

這幾種方式都會使this的指向變為當前調用的object。
  【函數refer的例子】 複製代碼 代碼如下:element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element onclick="doSomething()">

這幾種方式都不會改變函數的擁有者,其中要注意的是addEventListener和attachEvent是不一致的,因為attachEvent其實是建立了一個reference到了doSomething,而不是copy了這個函數。

  【用call的方式】
剛才我們說了,寫成<element onclick="test()">的方式還是不能讓test()的擁有者變成<element>,那我們可以這樣做 複製代碼 代碼如下:<element onclick="test(this)">
function (o) {
o.title = 'me';
}

這樣顯式的調用是可以的。或者,用call或apply這種對象冒充的繼承方式也可以 複製代碼 代碼如下:<element onclick="test.call(this)">
function test () {
this.title = 'me';
}

這也是對象冒充最典型的方式。

  【自由變數問題】
  寫了這麼長,我們還是回到最開始的那個問題: 複製代碼 代碼如下:var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());

為什麼這種方式得到的結果會是:hong 呢?重點在 複製代碼 代碼如下:return function(){
return this.name;
};

對比一下上面寫的函數refer的例子,不難發現,返回的這個匿名函數的調用方式和onclick = function () {doSomething()} 如出一轍。所以這種方式並不會改變這個function的擁有者,它雖然是個嵌套函數,但是它的聲明卻是頂級的。其中的this指向的是window。
  而第二種方式是強制在getName()中把this賦給了that,也就是說,that.name其實和getName()中的this.name是一樣的。而在getName的上下文中,它的擁有者是obj這個對象,所以this會指向obj,故this.name === obj.name;
  繞了這麼一大圈不知道有沒有把各位繞明白。

  其實可以這樣總結:在this所在的函數上下文中,如果這個函數不是以“方法”的形式被調用的話,那麼這個this會指向window對象,否則會指向這個函數的擁有者。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.