this容易混淆的示例
阿新 • • 發佈:2018-09-19
bubuko body time 多說 bsp 技術分享 對象 瀏覽器 為什麽
【註】this 永遠不會混亂,混亂的是我們而已。
/*
this永遠指向當前函數的主人。
this混亂:
1、添加了定時器/延時器
2、事件綁定
【註】函數如果發生了賦值,this就混亂了。
*/
示例1和示例2是在事件綁定時出現this混亂的現象
示例1
目的:點擊頁面上的按鈕時也 能彈出 10
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6View Code<script> 7 /* 8 this永遠指向當前函數的主人。 9 10 this混亂: 11 1、添加了定時器/延時器 12 2、事件綁定 13 【註】函數如果發生了賦值,this就混亂了。 14 */ 15 function Aaa(){ 16 this.a = 10; 17 18 //事件綁定 函數的主人換了 19 document.getElementById(‘btn1‘).onclick = this.show; 20 } 21 22 /*在function Aaa的this指向的肯等是 Aaa 的主人, 既 對象a1 23 所以 24 document.getElementById(‘btn1‘).onclick = this.show;就等價於 25 document.getElementById(‘btn1‘).onclick = a1.show; a1.show是對象26 a1的方法。所以又等價於: 27 document.getElementById(‘btn1‘).onclick = function(){alert(this.a);}; 28 到此時問題就來了,那麽上面這段代碼裏的this就不是指向對象a1了,此時它還 29 是指向函數的主人,但是這個主人就變成了 點擊事件的btn1對象了。 30 所以當我們點擊頁面上的按鈕時會顯示 undefined。 31 */ 32 33 Aaa.prototype.show = function(){ 34 alert(this.a); 35 } 36 37 /*var a1 = new Aaa(); 38 alert(a1.a); 39 a1.show();*/ 40 41 window.onload = function(){ 42 var a1 = new Aaa();//通過調用Aaa函數創建了a1對象 43 alert(a1.a);//10 44 a1.show();//10 45 } 46 47 </script> 48 </head> 49 <body> 50 <button id = "btn1">按鈕</button> 51 </body> 52 </html>
瀏覽器效果:
可以看出點擊頁面按鈕時沒有彈出10,既出現了this混亂,混亂的原因已經寫在代碼中
下面我們來看解決的方案:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script> 7 /* 8 this永遠指向當前函數的主人。 9 10 this混亂: 11 1、添加了定時器/延時器 12 2、事件綁定 13 【註】函數如果發生了賦值,this就混亂了。 14 */ 15 function Aaa(){ 16 this.a = 10; 17 18 var _this = this; 19 20 //事件綁定 函數的主人換了 21 document.getElementById(‘btn1‘).onclick = function(){ 22 _this.show(); 23 }; 24 } 25 26 /*通過變量_this來記錄函數function Aaa(){}的this既a1,然後在綁定的點擊事件函數 27 裏用_this來調用對象a1的show方法,這樣就避免了點擊事件裏的this指向點擊事件對象了。 28 document.getElementById(‘btn1‘).onclick = function(){ _this.show()};就等價於 29 document.getElementById(‘btn1‘).onclick = function(){ a1.show()};,這樣就避免了 30 this混亂了。 31 */ 32 33 34 Aaa.prototype.show = function(){ 35 alert(this.a); 36 } 37 38 /*var a1 = new Aaa(); 39 alert(a1.a); 40 a1.show();*/ 41 42 window.onload = function(){ 43 var a1 = new Aaa(); 44 alert(a1.a);//10 45 a1.show();//10 46 47 //點擊頁面按鈕是也可以正常調用 對象a1的show方法 ,結果:10 48 } 49 50 </script> 51 </head> 52 <body> 53 <button id = "btn1">按鈕</button> 54 </body> 55 </html>View Code
效果:
問題解決。
我們再來看一下在定時器或者延時器中,出現的現象:
示例3:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script> 7 //給對象b1添加屬性 8 function Bbb(){//此函數裏this的主人為對象b1,不多說 9 this.b = 20; 10 11 //傳參 == 賦值 12 setTimeout(this.show, 4000); 13 } 14 15 16 //給對象b1添加方法 17 Bbb.prototype.show = function(){//此函數裏this的主人為對象b1,不多說 18 alert(this); 19 } 20 21 var b1 = new Bbb();//通過調用函數Bbb的方式創建對象b1 22 alert(b1.b);//20 23 b1.show();//[object Object] 說明是對象 b1 24 25 /* 26 上面的延時器過了4s後彈出的 是[object Window],可能有人認為4s後會彈出 27 [object Object]。為什麽會出現這中現象呢。因為延時器的格式為 28 setTimeout(函數名或匿名函數(這裏是參數),延時毫秒數)。 29 因為傳參=賦值。 30 因為 31 setTimeout(this.show, 4000); 32 在函數Bbb裏,所以這裏面的this都指向b1, 33 所以就等價於 34 setTimeout(b1.show, 4000); 35 因為b1.show又等於函數function(){alert(this);} 36 所以等價於 37 setTimeout(function(){alert(this);}, 4000); 38 到此步驟,this就發生變化了,因為延時器setTimeout是系統調用的,所以此時 39 setTimeout裏的this就變成了[object Window]window對象。 40 41 */ 42 43 44 45 </script> 46 </head> 47 <body> 48 49 </body> 50 </html>View Code
瀏覽器效果;
問題原因見代碼註釋。
上面現象解決方案:
和上面一樣主要是自定義一個變量,用來儲存當前的this
示例4
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script> 7 function Bbb(){ 8 this.b = 20; 9 var _this = this; 10 11 //傳參 == 賦值 12 setTimeout(function(){ 13 _this.show(); 14 }, 4000); 15 } 16 Bbb.prototype.show = function(){ 17 alert(this.b); 18 } 19 20 var b1 = new Bbb(); 21 alert(b1.b);//20 22 b1.show();//20 23 24 /* 25 4s後彈出的是20, 26 27 用自定義變量記錄函數Bbb裏的this 既 b1,然後在匿名函數裏調用b1的show方法即可,然後用 28 匿名函數的方式給setTimeout傳參。 29 setTimeout(function(){ _this.show();}, 4000); 30 等價於 31 setTimeout(function(){ b1.show();}, 4000); 32 所以每次都不會混亂了。 33 */ 34 35 36 </script> 37 </head> 38 <body> 39 40 </body> 41 </html>View Code
效果:
this容易混淆的示例