this容易混淆的示例

Posted taohuaya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了this容易混淆的示例相关的知识,希望对你有一定的参考价值。

【注】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容易混淆的示例的主要内容,如果未能解决你的问题,请参考以下文章

10个JavaScript代码片段,使你更加容易前端开发。

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?

append() 在这个代码片段中是如何工作的?与特定变量混淆[重复]

php手动可见性示例混淆

sublime代码片段

html中常用的标签代码容易记混淆怎么办?