说说this

说到js我们就不得不多this,这东西很多时候让人不知道它代表了谁?我们根据js的书写场景简单看看this在不同地方都代表谁。

1.在全局下,this的指向

我们运行下面页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>

</body>
<script>
alert(this);
</script>
</html>

弹出:

说说this_第1张图片

说明this代表了window对象,也就是指向window。

我们知道全局设置的变量等都是挂载window下的,可以通过window.xx获取到,同样window也可以缺省(就是不写):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>

</body>
<script>
var a=123;
var b=456;
alert(a)
alert(window.a);
alert(this.a);
</script>
</html>

三种写法都可输出变量a的值,window使我们js的全局对象,除了我们自定义全局变量挂载他的下面,很多原生提供的东西都是挂在window下的:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>

</body>
<script>
alert(document.documentElement.tagName);
alert(window.document.documentElement.tagName);
alert(setInterval);
alert(window.setInterval);
alert(parseInt);
alert(window.parseInt);
</script>
</html>

是不是通过window.也可以调用。

总结就是全局下的this就是指代window,window是js的根,很多东西都挂在在window下,可以通过window去访问,同样缺省可用。

2.dom+事件的this

我们操作页面,交互的核心之一就是事件,事件触发,我们为了让js可以正常的运行,一般会这样书写:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>

</body>
<script>
window.onload=function(){
 alert(this);
};
</script>
</html>

load事件中书写代码,这样就可以保证页面加载完去执行,这时候this发现指向了window,我们好像看不出来什么,我们在页面写几个标签,然后加入click事件,去弹出this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var abc=document.getElementById("abc");
 var dom=document.getElementById("dom");
 abc.onclick=function(){
  alert(this);
 };
 dom.onclick=function(){
  alert(this);
 };
};
</script>
</html>

div和p点击弹出情况:

 

说说this_第2张图片

说说this_第3张图片

点击div是指向div元素,点击p指向p元素(p的全名),我们可能还疑惑,我们更具体输出内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var abc=document.getElementById("abc");
 var dom=document.getElementById("dom");
 abc.onclick=function(){
  alert(this.innerHTML);
 };
 dom.onclick=function(){
  alert(this.innerHTML);
 };
};
</script>
</html>

弹出:

 

说说this_第4张图片

说说this_第5张图片

这次是不是完全清楚了,点击那个this就指向了那个元素,我们利用dom具有的属性就可以具体输出对应内容。

此时我们知道了this指向的就是添加事件的对象元素(也就是标签),上面window加入load事件,this指向的是window也就是添加load事件对象。

总结,在添加事件后,this指向添加事件的对象,并且指向的是最近的对象,div就指向div而不是window。

3.this在事件中指向冲突问题

我们在上面例子,知道this指向有就近的原则一样,根据所在位置,所在环境会指向最近的那个对象,比如div中的this就是指向div,我们往上反一级的this就指向了window,知道this所指向受到上下文影响。

我们执行下面的例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var abc=document.getElementById("abc");
 var dom=document.getElementById("dom");
 abc.onclick=function(){
  setInterval(function(){
   this.innerHTML=this.innerHTML+1;
  },500);
 };
 dom.onclick=function(){
  alert(this.innerHTML);
 };
};
</script>
</html>

我想做的就是点击后,内部的内容不断+1,可是我们发现并没有+1,

我把setinterval补全:

我们使用的这个方法是通过window调用,根据this指向上下文对象,猜测this指向了window,所以不出现想要结果,我们测试this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var abc=document.getElementById("abc");
 var dom=document.getElementById("dom");
 abc.onclick=function(){
  window.setInterval(function(){
   alert(this)
   //this.innerHTML=this.innerHTML+1;
  },500);
 };
 dom.onclick=function(){
  alert(this.innerHTML);
 };
};
</script>
</html>

点击后,不断弹出:

说说this_第6张图片

说明间隔函数的this替掉事件this了,没有指向div,简单就是名字一样了,最简单解决思路就是外部或者内部把this赋值到其他名字变量里,这样就不会冲突了:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var abc=document.getElementById("abc");
 var dom=document.getElementById("dom");
 abc.onclick=function(){
  var that=this;
  window.setInterval(function(){
   that.innerHTML=that.innerHTML+1;
  },500);
 };
 dom.onclick=function(){
  alert(this.innerHTML);
 };
};
</script>
</html>

说说this_第7张图片

是不是开始不断+1,把事件this赋值给that,我们的间隔函数去获取that执行处理。有人可定想间隔里面this给that,但是this还是this也就是window,这明显是不可行的。

总结冲突问题,把外部this指向内容赋值给自定义变量。

4.类和this

我们上面都是说事件中的this,下面介绍在语法中this的指向问题。

标题是类和this,类就是创建对象用的,我们从对象入手,然后介绍类中的this。

1.对象类型和this

我们创建对象和输出this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var obj={};
 obj.a=123;
 obj.b=function(){alert(this)};
 obj.b();
 
};
</script>
</html>

弹出obj,猜测是指向定义的obj了,进一步测试:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 var obj={};
 obj.a=123;
 obj.b=function(){alert(this.a)};
 obj.b();
 
};
</script>
</html>

弹出:

说说this_第8张图片

也就是输入obj的a属相值,说明obj类型内this指向的就是本身。

2.类和this

类可以创建对象,这个我们肯定非常熟悉,指代this指向的就是每次创建的对象,

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 function Aa(arg){
  this.a=arg;
 };
 
 alert(new Aa(1).a);
 alert(new Aa(2).a);
};
</script>
</html>

类里面的this就是每次创建的对象,类是抽象和相似定义,避免了下面这种创建对象的重复性:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 function Aa(arg){
  this.a=arg;
 };
 
 alert(new Aa(1).a);
 alert(new Aa(2).a);
 
 var obj1={a:1};
 var obj2={a:2};
 
 alert(obj1.a);
 alert(obj2.a);
};
</script>
</html>

类里面的this同样具有冲突问题,比如类里面调用setinterval方法去改变某个属性,那么是不是间隔this指向的是window,我们this.a就不能去改变了,解决冲突我们还是可以利用that这种方式:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 function Aa(id){
  this.a=document.getElementById(id);
  var that=this;
  this.init=function(){
   this.add();
  }
  this.add=function(){
   setInterval(function(){
    that.a.innerHTML=that.a.innerHTML+1;
   },500)
  };
 };
 
 new Aa("abc").init();
 new Aa("dom").init();
 
};
</script>
</html>

说说this_第9张图片

 

是不是就成功实现了两个元素内容增加,每次new都是开辟空间让对象对执行对象处理。

我们可能还如加入事件处理,更加的复杂封装:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 function Aa(id){
  this.a=document.getElementById(id);
  var that=this;
  this.init=function(){
   this.a.onclick=function(){
    this.add();
   };
  }
  this.add=function(){
   setInterval(function(){
    that.a.innerHTML=that.a.innerHTML+1;
   },500)
  };
 };
 
 new Aa("abc").init();
 new Aa("dom").init();
 
};
</script>
</html>

说说this_第10张图片

执行失败,我们仔细分析,发现事件this只的是this.a,就是指向的元素;我们调用add方法挂在指向new的对象this,而不是指向元素this。

既然冲突了,还是利用that处理:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 function Aa(id){
  this.a=document.getElementById(id);
  var that=this;
  this.init=function(){
   this.a.onclick=function(){
    that.add();
   };
  }
  this.add=function(){
   setInterval(function(){
    that.a.innerHTML=that.a.innerHTML+1;
   },500)
  };
 };
 
 new Aa("abc").init();
 new Aa("dom").init();
 
};
</script>
</html>

说说this_第11张图片

that肯定指向new的对象,局部this不会替换他,我们就可以调用到了。

5.事件this的相等判断

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 
 var abc=document.getElementById("abc");
 
 abc.onclick=function(){
  if(this==abc){
   alert(1);
  }else{
   alert(2);
  };
 }; 
 
};
</script>
</html>

核心测试:

说说this_第12张图片

相等判断没有问题,我们知道this和abc代表的是元素对象,我们就会想到obj类型有没有相等判断能力:

 var obj1={a:1};
 var obj2={a:1};
 if(obj1==obj2){
  alert(1);
 }else{
  alert(2);
 };

1和2证明不是相同的东西:

 var obj1=123;
 var obj2=123;
 if(obj1==obj2){
  alert(1);
 }else{
  alert(2);
 };

1和2相同,在一些特殊类型是不具有判断能力的。

上面是自己琢磨的问题,还是回到事件和this,我们知道找div除了用id还有其他方法,我们测试:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <style>
 *{ margin:0; padding:0;}
 html{height:100%;}
 body{height:100%;}
    
    </style>
</head>
<body>
   
<div style="height:100px;" id="abc">789</div>
<p style="height:100px;" id="dom">dom</p>
</body>
<script>
window.onload=function(){
 
 var abc=document.getElementById("abc");
 var abc2=document.getElementsByTagName("div")[0];
 abc.onclick=function(){
  if(this==abc2){
   alert(1);
  }else{
   alert(2);
  };
 };
 abc2.onmousemove=function(){
  if(abc2==abc){
   alert(3);
  }else{
   alert(4);
  };
 }; 
 
};
</script>
</html>

给abc和abc2都可以监听事件,说明可以多对一的操作元素对象。同样不同方式找到的元素如果代表同一个元素有判断相等能力。

你可能感兴趣的:(js,this)