關(guān)于javascript中this關(guān)鍵字(翻譯+自我理解)
更新時(shí)間:2010年10月20日 12:12:32 作者:
在傳統(tǒng)面向?qū)ο笳Z言中,this關(guān)鍵字是個(gè)很乖的小孩,從不亂跑,該是誰的就是誰的??墒窃贘avaScript中,我們發(fā)現(xiàn)它不那么乖,有時(shí)甚至把我們搞的暈頭轉(zhuǎn)向的。所以有必要對它稍微做個(gè)總結(jié)。
下文有大概70%的內(nèi)容出自http://www.quirksmode.org/js/this.html,另外30%是我自己對它的理解和感想。希望能對有需要的人一點(diǎn)幫助。。。
首先,先看一個(gè)很典型的關(guān)于this關(guān)鍵字題目:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());
這里也不賣關(guān)子了,執(zhí)行結(jié)果為:hong
稍微改下代碼:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
var that = this;
return function(){
return that.name;
};
}
}
alert(obj.getName()());
執(zhí)行結(jié)果為:ru
執(zhí)行結(jié)果為:ru
關(guān)于出現(xiàn)這種結(jié)果的原因,下面會細(xì)細(xì)討論。
【函數(shù)的擁有者】
要解釋this,要先說這個(gè)概念。在JavaScript里,this始終指向我們當(dāng)前正在執(zhí)行的函數(shù)的“擁有者”。更為確切的說:是指向把這個(gè)函數(shù)作為方法的對象。
這句話怎么理解,我們可以看看下面的例子:
/* -- test1 -- */
function test1 () {
this.title = 'me';
alert(window['title']);
alert(this === window); //true
}
test1();
執(zhí)行結(jié)果為:me, true
在上例中,this是指向window對象的。并把window這個(gè)對象的title屬性寫為'me',因?yàn)閠est1是個(gè)頂級函數(shù),所以它的擁有者是window對象,或者說它是window對象的一個(gè)方法。這個(gè)應(yīng)該不難理解。比如上面調(diào)用test1()時(shí),也可以寫成 window.test1();這樣的明了了。
接下來,我們建一個(gè)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>
點(diǎn)擊div結(jié)果為:undefined, false; 同時(shí)我們用firebug可以看到‘me'這個(gè)屬性值其實(shí)是被賦給了id為‘o'的這個(gè)HtmlObject

顯而易見,此時(shí)this指向了這個(gè)div,也就是說,test1()的擁有者變成了div這個(gè)HtmlObject,或者說它變成了div的onclick方法來調(diào)用。這種情況應(yīng)該還是容易理解的。
下面我們接著改代碼,就改一個(gè)地方:
o.onclick = test1(); // 注意:這里加了個(gè)括號
把上面代碼的最后一句改成這樣后,點(diǎn)擊div運(yùn)行的結(jié)果為:me, true
變成了和第一種情況一樣了,this指向了window。有人會納悶,覺得沒什么區(qū)別,其實(shí)是有區(qū)別的。這里涉及到函數(shù)的copy和refer的問題。
【函數(shù)的Copy】
如果通過
o.onclick = test1;
這樣的方式的話,其實(shí)是把test1() 這個(gè)函數(shù)Copy給了對象 o 的 onclick 屬性。因此test1的擁有者變成了 o 這個(gè)對象。
如果通過
o.onclick = test1();
這樣的方式的話,本質(zhì)上是指當(dāng)獲取到點(diǎn)擊事件的handle時(shí),指引它去執(zhí)行test1()函數(shù)。注意是指引去執(zhí)行而不是賦給它去執(zhí)行。test1()的擁有者沒變,還是window.
【函數(shù)的Refer】
同上,我們通過inline的方式把調(diào)用寫到html里來調(diào)用的話,還是refer的方式
<div id="o" style="width:50px;height:50px;border:4px solid #333" onclick="test1()">me!</div>
點(diǎn)擊div執(zhí)行結(jié)果還是表示this指向window。
【函數(shù)copy的例子】
element.onclick = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element onclick="this.style.color = '#cc0000';">
這幾種方式都會使this的指向變?yōu)楫?dāng)前調(diào)用的object。
【函數(shù)refer的例子】
element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element onclick="doSomething()">
這幾種方式都不會改變函數(shù)的擁有者,其中要注意的是addEventListener和attachEvent是不一致的,因?yàn)閍ttachEvent其實(shí)是建立了一個(gè)reference到了doSomething,而不是copy了這個(gè)函數(shù)。
【用call的方式】
剛才我們說了,寫成<element onclick="test()">的方式還是不能讓test()的擁有者變成<element>,那我們可以這樣做
<element onclick="test(this)">
function (o) {
o.title = 'me';
}
這樣顯式的調(diào)用是可以的?;蛘?,用call或apply這種對象冒充的繼承方式也可以
<element onclick="test.call(this)">
function test () {
this.title = 'me';
}
這也是對象冒充最典型的方式。
【自由變量問題】
寫了這么長,我們還是回到最開始的那個(gè)問題:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());
為什么這種方式得到的結(jié)果會是:hong 呢?重點(diǎn)在
return function(){
return this.name;
};
對比一下上面寫的函數(shù)refer的例子,不難發(fā)現(xiàn),返回的這個(gè)匿名函數(shù)的調(diào)用方式和onclick = function () {doSomething()} 如出一轍。所以這種方式并不會改變這個(gè)function的擁有者,它雖然是個(gè)嵌套函數(shù),但是它的聲明卻是頂級的。其中的this指向的是window。
而第二種方式是強(qiáng)制在getName()中把this賦給了that,也就是說,that.name其實(shí)和getName()中的this.name是一樣的。而在getName的上下文中,它的擁有者是obj這個(gè)對象,所以this會指向obj,故this.name === obj.name;
繞了這么一大圈不知道有沒有把各位繞明白。
其實(shí)可以這樣總結(jié):在this所在的函數(shù)上下文中,如果這個(gè)函數(shù)不是以“方法”的形式被調(diào)用的話,那么這個(gè)this會指向window對象,否則會指向這個(gè)函數(shù)的擁有者。
首先,先看一個(gè)很典型的關(guān)于this關(guān)鍵字題目:
復(fù)制代碼 代碼如下:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());
這里也不賣關(guān)子了,執(zhí)行結(jié)果為:hong
稍微改下代碼:
復(fù)制代碼 代碼如下:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
var that = this;
return function(){
return that.name;
};
}
}
alert(obj.getName()());
執(zhí)行結(jié)果為:ru
執(zhí)行結(jié)果為:ru
關(guān)于出現(xiàn)這種結(jié)果的原因,下面會細(xì)細(xì)討論。
【函數(shù)的擁有者】
要解釋this,要先說這個(gè)概念。在JavaScript里,this始終指向我們當(dāng)前正在執(zhí)行的函數(shù)的“擁有者”。更為確切的說:是指向把這個(gè)函數(shù)作為方法的對象。
這句話怎么理解,我們可以看看下面的例子:
復(fù)制代碼 代碼如下:
/* -- test1 -- */
function test1 () {
this.title = 'me';
alert(window['title']);
alert(this === window); //true
}
test1();
執(zhí)行結(jié)果為:me, true
在上例中,this是指向window對象的。并把window這個(gè)對象的title屬性寫為'me',因?yàn)閠est1是個(gè)頂級函數(shù),所以它的擁有者是window對象,或者說它是window對象的一個(gè)方法。這個(gè)應(yīng)該不難理解。比如上面調(diào)用test1()時(shí),也可以寫成 window.test1();這樣的明了了。
接下來,我們建一個(gè)div,并把test1作為方法賦給div的onclick屬性:
復(fù)制代碼 代碼如下:
<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>
點(diǎn)擊div結(jié)果為:undefined, false; 同時(shí)我們用firebug可以看到‘me'這個(gè)屬性值其實(shí)是被賦給了id為‘o'的這個(gè)HtmlObject

顯而易見,此時(shí)this指向了這個(gè)div,也就是說,test1()的擁有者變成了div這個(gè)HtmlObject,或者說它變成了div的onclick方法來調(diào)用。這種情況應(yīng)該還是容易理解的。
下面我們接著改代碼,就改一個(gè)地方:
復(fù)制代碼 代碼如下:
o.onclick = test1(); // 注意:這里加了個(gè)括號
把上面代碼的最后一句改成這樣后,點(diǎn)擊div運(yùn)行的結(jié)果為:me, true
變成了和第一種情況一樣了,this指向了window。有人會納悶,覺得沒什么區(qū)別,其實(shí)是有區(qū)別的。這里涉及到函數(shù)的copy和refer的問題。
【函數(shù)的Copy】
如果通過
復(fù)制代碼 代碼如下:
o.onclick = test1;
這樣的方式的話,其實(shí)是把test1() 這個(gè)函數(shù)Copy給了對象 o 的 onclick 屬性。因此test1的擁有者變成了 o 這個(gè)對象。
如果通過
復(fù)制代碼 代碼如下:
o.onclick = test1();
這樣的方式的話,本質(zhì)上是指當(dāng)獲取到點(diǎn)擊事件的handle時(shí),指引它去執(zhí)行test1()函數(shù)。注意是指引去執(zhí)行而不是賦給它去執(zhí)行。test1()的擁有者沒變,還是window.
【函數(shù)的Refer】
同上,我們通過inline的方式把調(diào)用寫到html里來調(diào)用的話,還是refer的方式
復(fù)制代碼 代碼如下:
<div id="o" style="width:50px;height:50px;border:4px solid #333" onclick="test1()">me!</div>
點(diǎn)擊div執(zhí)行結(jié)果還是表示this指向window。
【函數(shù)copy的例子】
復(fù)制代碼 代碼如下:
element.onclick = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element onclick="this.style.color = '#cc0000';">
這幾種方式都會使this的指向變?yōu)楫?dāng)前調(diào)用的object。
【函數(shù)refer的例子】
復(fù)制代碼 代碼如下:
element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element onclick="doSomething()">
這幾種方式都不會改變函數(shù)的擁有者,其中要注意的是addEventListener和attachEvent是不一致的,因?yàn)閍ttachEvent其實(shí)是建立了一個(gè)reference到了doSomething,而不是copy了這個(gè)函數(shù)。
【用call的方式】
剛才我們說了,寫成<element onclick="test()">的方式還是不能讓test()的擁有者變成<element>,那我們可以這樣做
復(fù)制代碼 代碼如下:
<element onclick="test(this)">
function (o) {
o.title = 'me';
}
這樣顯式的調(diào)用是可以的?;蛘?,用call或apply這種對象冒充的繼承方式也可以
復(fù)制代碼 代碼如下:
<element onclick="test.call(this)">
function test () {
this.title = 'me';
}
這也是對象冒充最典型的方式。
【自由變量問題】
寫了這么長,我們還是回到最開始的那個(gè)問題:
復(fù)制代碼 代碼如下:
var name = 'hong'
var obj = {
name: 'ru',
getName: function(){
return function(){
return this.name;
};
}
}
alert(obj.getName()());
為什么這種方式得到的結(jié)果會是:hong 呢?重點(diǎn)在
復(fù)制代碼 代碼如下:
return function(){
return this.name;
};
對比一下上面寫的函數(shù)refer的例子,不難發(fā)現(xiàn),返回的這個(gè)匿名函數(shù)的調(diào)用方式和onclick = function () {doSomething()} 如出一轍。所以這種方式并不會改變這個(gè)function的擁有者,它雖然是個(gè)嵌套函數(shù),但是它的聲明卻是頂級的。其中的this指向的是window。
而第二種方式是強(qiáng)制在getName()中把this賦給了that,也就是說,that.name其實(shí)和getName()中的this.name是一樣的。而在getName的上下文中,它的擁有者是obj這個(gè)對象,所以this會指向obj,故this.name === obj.name;
繞了這么一大圈不知道有沒有把各位繞明白。
其實(shí)可以這樣總結(jié):在this所在的函數(shù)上下文中,如果這個(gè)函數(shù)不是以“方法”的形式被調(diào)用的話,那么這個(gè)this會指向window對象,否則會指向這個(gè)函數(shù)的擁有者。
您可能感興趣的文章:
- 精通JavaScript的this關(guān)鍵字
- javascript與jquery中的this關(guān)鍵字用法實(shí)例分析
- 跟我學(xué)習(xí)javascript的this關(guān)鍵字
- 圖解JavaScript中的this關(guān)鍵字
- 關(guān)于js里的this關(guān)鍵字的理解
- JavaScript中的this關(guān)鍵字使用詳解
- 深入理解Javascript中的this關(guān)鍵字
- Javascript中this關(guān)鍵字的一些小知識
- JavaScript中的this關(guān)鍵字使用方法總結(jié)
- Javascript之this關(guān)鍵字深入解析
- js中的this關(guān)鍵字詳解
- JavaScript中的this關(guān)鍵字介紹與使用實(shí)例
- javascript中this關(guān)鍵字詳解
相關(guān)文章
微信小程序?qū)崿F(xiàn)給嵌套template模板傳遞數(shù)據(jù)的方式總結(jié)
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)給嵌套template模板傳遞數(shù)據(jù)的方式,結(jié)合實(shí)例形式總結(jié)分析了微信小程序嵌套template模板的定義、調(diào)用、參數(shù)傳遞及相關(guān)使用技巧,需要的朋友可以參考下2017-12-12
textarea 控制輸入字符字節(jié)數(shù)(示例代碼)
本篇文章主要是對textarea 控制輸入字符字節(jié)數(shù)的示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
JavaScript返回0-1之間隨機(jī)數(shù)的方法
這篇文章主要介紹了JavaScript返回0-1之間隨機(jī)數(shù)的方法,涉及javascript中Math對象random方法的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
淺談JavaScript宏任務(wù)和微任務(wù)執(zhí)行順序
本文主要介紹了JavaScript宏任務(wù)和微任務(wù)執(zhí)行順序,結(jié)合實(shí)例代碼進(jìn)行了詳細(xì)的講解,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06
詳解JavaScript基于面向?qū)ο笾畡?chuàng)建對象(1)
這篇文章主要介紹了JavaScript基于面向?qū)ο笾畡?chuàng)建對象,對創(chuàng)建對象進(jìn)行了詳細(xì)描述,感興趣的小伙伴們可以參考一下2015-12-12
微信小程序?qū)崿F(xiàn)多選框全選與取消全選功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)多選框全選與取消全選功能,結(jié)合實(shí)例形式分析了微信小程序多選框功能實(shí)現(xiàn)、布局顯示及全選、取消全選相關(guān)操作技巧,需要的朋友可以參考下2019-05-05

