1. 程式人生 > >this容易混淆的示例

this容易混淆的示例

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>
 6
<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>
View Code

瀏覽器效果:

技術分享圖片

可以看出點擊頁面按鈕時沒有彈出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容易混淆的示例