说到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代表了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点击弹出情况:
点击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就指向了那个元素,我们利用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替掉事件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>
是不是开始不断+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>
弹出:
也就是输入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>
是不是就成功实现了两个元素内容增加,每次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只的是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>
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和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都可以监听事件,说明可以多对一的操作元素对象。同样不同方式找到的元素如果代表同一个元素有判断相等能力。