亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

跟我學(xué)習(xí)javascript的this關(guān)鍵字

 更新時間:2020年05月28日 15:47:07   作者:小平果118  
跟我學(xué)習(xí)javascript的this關(guān)鍵字,this是動態(tài)綁定,或稱為運行期綁定的,這就導(dǎo)致 JavaScript中的this關(guān)鍵字有能力具備多重含義,帶來靈活性的同時,也為初學(xué)者帶來不少困惑

本文僅就這一問題展開討論,閱罷本文,讀者若能正確回答 JavaScript 中的 What 's this 問題,作為作者,我就會覺得花費這么多功夫,撰寫這樣一篇文章是值得的。

我們要記住一句話:this永遠(yuǎn)指向函數(shù)運行時所在的對象!而不是函數(shù)被創(chuàng)建時所在的對象。也即:誰調(diào)用,指向誰。切記…

本文將分三種情況來分析this對象到底身處何方。

1、普通函數(shù)中的this

無論this身處何處,第一要務(wù)就是要找到函數(shù)運行時的位置。

 var name="全局";
 function getName(){
  var name="局部";
  return this.name;
 };
 alert(getName());

當(dāng)this出現(xiàn)在全局環(huán)境的函數(shù)getName中時,此時函數(shù)getName運行時的位置在

alert(getName());

顯然,函數(shù)getName所在的對象是全局對象,即window,因此this的安身之處定然在window。此時的this指向window對象,則getName返回的this.name其實是window.name,因此alert出來的是“全局”!

那么,當(dāng)this不是出現(xiàn)在全局環(huán)境的函數(shù)中,而是出現(xiàn)在局部環(huán)境的函數(shù)中時,又會身陷何方呢?

 var name="全局";
 var xpg={
  name:"局部",
  getName:function(){
   return this.name;
  }
 };
 alert(xpg.getName());

其中this身處的函數(shù)getName不是在全局環(huán)境中,而是處在xpg環(huán)境中。無論this身處何處,一定要找到函數(shù)運行時的位置。此時函數(shù)getName運行時的位置

alert(xpg.getName());

顯然,函數(shù)getName所在的對象是xpg,因此this的安身之處定然在xpg,即指向xpg對象,則getName返回的this.name其實是xpg.name,因此alert出來的是“局部”!

舉個例子鞏固一下:

var someone = {
 name: "Bob",
 showName: function(){
  alert(this.name);
 }
};

var other = {
 name: "Tom",
 showName: someone.showName
}

other.showName();  //Tom

this關(guān)鍵字雖然是在someone.showName中聲明的,但運行的時候是other.showName,所以this指向other.showName函數(shù)的當(dāng)前對象,即other,故最后alert出來的是other.name。

2、閉包中的this

閉包也是個不安分子,本文暫且不對其過于贅述,簡而言之:所謂閉包就是在一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù),且內(nèi)部函數(shù)訪問了外部的變量。
浪子this與痞子閉包混在一起,可見將永無寧日啊!

 var name="全局";
 var xpg={
  name:"局部",
  getName:function(){
   return function(){
    return this.name;
   };
  }
 };
 alert(xpg.getName()());

此時的this明顯身處困境,竟然處在getName函數(shù)中的匿名函數(shù)里面,而該匿名函數(shù)又調(diào)用了變量name,因此構(gòu)成了閉包,即this身處閉包中。
無論this身處何處,一定要找到函數(shù)運行時的位置。此時不能根據(jù)函數(shù)getName運行時的位置來判斷,而是根據(jù)匿名函數(shù)的運行時位置來判斷。

function (){
 return this.name;
};

顯然,匿名函數(shù)所在的對象是window,因此this的安身之處定然在window,則匿名函數(shù)返回的this.name其實是window.name,因此alert出來的就是“全局”!

那么,如何在閉包中使得this身處在xpg中呢?—緩存this

 var name="全局";
 var xpg={
  name:"局部",
  getName:function(){
   var that=this;
   return function(){
    return that.name;
   };
  }
 };
 alert(xpg.getName()());

在getName函數(shù)中定義that=this,此時getName函數(shù)運行時位置在

alert(xpg.getName());

則this指向xpg對象,因此that也指向xpg對象。在閉包的匿名函數(shù)中返回that.name,則此時返回的that.name其實是xpg.name,因此就可以alert出來 “局部”!

3、new關(guān)鍵字創(chuàng)建新對象

new關(guān)鍵字后的構(gòu)造函數(shù)中的this指向用該構(gòu)造函數(shù)構(gòu)造出來的新對象:

function Person(__name){
 this.name = __name;  //這個this指向用該構(gòu)造函數(shù)構(gòu)造的新對象,這個例子是Bob對象
}
Person.prototype.show = function(){
 alert(this.name); //this 指向Person,this.name = Person.name;
}

var Bob = new Person("Bob");
Bob.show();  //Bob

4、call與apply中的this

在JavaScript中能管的住this的估計也就非call與apply莫屬了。
call與apply就像this的父母一般,讓this住哪它就得住哪,不得不聽話!當(dāng)無參數(shù)時,當(dāng)前對象為window

var name="全局";
var xpg={
 name:"局部"
};
function getName(){
 alert(this.name);
}
getName(xpg);
getName.call(xpg);
getName.call();

其中this身處函數(shù)getName中。無論this身處何處,一定要找到函數(shù)運行時的位置。此時函數(shù)getName運行時的位置

getName(xpg);

顯然,函數(shù)getName所在的對象是window,因此this的安身之處定然在window,即指向window對象,則getName返回的this.name其實是window.name,因此alert出來的是“全局”!

那么,該call與apply登場了,因為this必須聽他們的指揮!
getName.call(xpg);
其中,call指定this的安身之處就是在xpg對象,因為this被迫只能在xpg那安家,則此時this指向xpg對象, this.name其實是xpg.name,因此alert出來的是“局部”!

5、eval中的this

對于eval函數(shù),其執(zhí)行時候似乎沒有指定當(dāng)前對象,但實際上其this并非指向window,因為該函數(shù)執(zhí)行時的作用域是當(dāng)前作用域,即等同于在該行將里面的代碼填進(jìn)去。下面的例子說明了這個問題:

var name = "window";

var Bob = {
 name: "Bob",
 showName: function(){
  eval("alert(this.name)");
 }
};

Bob.showName(); //Bob

6、沒有明確的當(dāng)前對象時的this

當(dāng)沒有明確的執(zhí)行時的當(dāng)前對象時,this指向全局對象window。
例如對于全局變量引用的函數(shù)上我們有:

var name = "Tom";

var Bob = {
 name: "Bob",
 show: function(){
  alert(this.name);
 }
}

var show = Bob.show;
show();  //Tom

你可能也能理解成show是window對象下的方法,所以執(zhí)行時的當(dāng)前對象時window。但局部變量引用的函數(shù)上,卻無法這么解釋:

var name = "window";

var Bob = {
 name: "Bob",
 showName: function(){
  alert(this.name);
 }
};

var Tom = {
 name: "Tom",
 showName: function(){
  var fun = Bob.showName;
  fun();
 }
};

Tom.showName();  //window

在瀏覽器中setTimeout、setInterval和匿名函數(shù)執(zhí)行時的當(dāng)前對象是全局對象window,這條我們可以看成是上一條的一個特殊情況。

var name = "Bob"; 
var nameObj ={ 
  name : "Tom", 
  showName : function(){ 
   alert(this.name); 
  }, 
  waitShowName : function(){ 
   setTimeout(this.showName, 1000); 
  } 
 }; 

 nameObj.waitShowName();

所以在運行this.showName的時候,this指向了window,所以最后顯示了window.name。

7、dom事件中的this

(1)你可以直接在dom元素中使用

<input id="btnTest" type="button" value="提交" onclick="alert(this.value))" />

分析:對于dom元素的一個onclick(或其他如onblur等)屬性,它為所屬的html元素所擁有,直接在它觸發(fā)的函數(shù)里寫this,this應(yīng)該指向該html元素。

(2)給dom元素注冊js函數(shù)
a、不正確的方式

<script type="text/javascript">
 function thisTest(){
 alert(this.value); // 彈出undefined, this在這里指向??
}
</script>
<input id="btnTest" type="button" value="提交" onclick="thisTest()" />

分析:onclick事件直接調(diào)用thisTest函數(shù),程序就會彈出undefined。因為thisTest函數(shù)是在window對象中定義的,
所以thisTest的擁有者(作用域)是window,thisTest的this也是window。而window是沒有value屬性的,所以就報錯了。
b、正確的方式

<input id="btnTest" type="button" value="提交" />

<script type="text/javascript">
 function thisTest(){
 alert(this.value); 
}
document.getElementById("btnTest").onclick=thisTest; //給button的onclick事件注冊一個函數(shù)
</script>

分析:在前面的示例中,thisTest函數(shù)定義在全局作用域(這里就是window對象),所以this指代的是當(dāng)前的window對象。而通過document.getElementById(“btnTest”).onclick=thisTest;這樣的形式,其實是將btnTest的onclick屬性設(shè)置為thisTest函數(shù)的一個副本,在btnTest的onclick屬性的函數(shù)作用域內(nèi),this歸btnTest所有,this也就指向了btnTest。其實如果有多個dom元素要注冊該事件,我們可以利用不同的dom元素id,用下面的方式實現(xiàn):

document.getElementById("domID").onclick=thisTest; //給button的onclick事件注冊一個函數(shù)。

因為多個不同的HTML元素雖然創(chuàng)建了不同的函數(shù)副本,但每個副本的擁有者都是相對應(yīng)的HTML元素,各自的this也都指向它們的擁有者,不會造成混亂。
為了驗證上述說法,我們改進(jìn)一下代碼,讓button直接彈出它們對應(yīng)的觸發(fā)函數(shù):

<input id="btnTest1" type="button" value="提交1" onclick="thisTest()" />
<input id="btnTest2" type="button" value="提交2" />

<script type="text/javascript">
function thisTest(){
this.value="提交中";
}
var btn=document.getElementById("btnTest1");
alert(btn.onclick); //第一個按鈕函數(shù)

var btnOther=document.getElementById("btnTest2");
btnOther.onclick=thisTest;
alert(btnOther.onclick); //第二個按鈕函數(shù)
</script>
其彈出的結(jié)果是:

//第一個按鈕
function onclick(){
 thisTest()
}

//第二個按鈕
function thisTest(){
 this.value="提交中";
}

從上面的結(jié)果你一定理解的更透徹了。
By the way,每新建一個函數(shù)的副本,程序就會為這個函數(shù)副本分配一定的內(nèi)存。而實際應(yīng)用中,大多數(shù)函數(shù)并不一定會被調(diào)用,于是這部分內(nèi)存就被白白浪費了。所以我們通常都這么寫:

<input id="btnTest1" type="button" value="提交1" onclick="thisTest(this)" />
<input id="btnTest2" type="button" value="提交2" onclick="thisTest(this)" />
<input id="btnTest3" type="button" value="提交3" onclick="thisTest(this)" />
<input id="btnTest4" type="button" value="提交4" onclick="thisTest(this)" />

<script type="text/javascript">
 function thisTest(obj){
 alert(obj.value); 
}
</script>

這是因為我們使用了函數(shù)引用的方式,程序就只會給函數(shù)的本體分配內(nèi)存,而引用只分配指針。這樣寫一個函數(shù),調(diào)用的地方給它分配一個(指針)引用,這樣效率就高很多。當(dāng)然,如果你覺得這樣注冊事件不能兼容多種瀏覽器,可以寫下面的注冊事件的通用腳本:

//js事件 添加 EventUtil.addEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名) 移除EventUtil.removeEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名)
var EventUtil = new eventManager();

//js事件通用管理器 dom元素 添加或者移除事件
function eventManager() {
 //添加事件
 //oDomElement:dom元素,如按鈕,文本,document等; ****** oEventType:事件名稱(如:click,如果是ie瀏覽器,自動將click轉(zhuǎn)換為onclick);****** oFunc:事件觸發(fā)的函數(shù)名
 this.addEvent = function(oDomElement, oEventType, oFunc) {
  //ie
  if (oDomElement.attachEvent) {
   oDomElement.attachEvent("on" + oEventType, oFunc);
  }
  //ff,opera,safari等
  else if (oDomElement.addEventListener) {
   oDomElement.addEventListener(oEventType, oFunc, false);
  }
  //其他
  else {
   oDomElement["on" + oEventType] = oFunc;
  }
 }

 this.removeEvent = function(oDomElement, oEventType, oFunc) {
  //ie
  if (oDomElement.detachEvent) {
   oDomElement.detachEvent("on" + oEventType, oFunc);
  }
  //ff,opera,safari等
  else if (oDomElement.removeEventListener) {
   oDomElement.removeEventListener(oEventType, oFunc, false);
  }
  //其他
  else {
   oDomElement["on" + oEventType] = null;
  }
 }
}

正像注釋寫的那樣,要注冊dom元素事件,用EventUtil.addEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名)即可,移除時可以這樣寫:EventUtil.removeEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名),這是題外話,不說了。

以上就是本文的全部內(nèi)容,希望通過這篇文章大家更加了解javascript的this關(guān)鍵字,大家共同進(jìn)步。

相關(guān)文章

最新評論