写js也有两年多了,在平时工作中也经常会用到this关键字,但是仅局限于用它,如果要求我讲明白this到底是什么的话可能就有点懵逼了,相信大家在面试的时候面试官也经常会问你this是神马东东,为了避免这种面试尴尬也是因为确实想把基础打扎实一点,所以就认认真真学了一遍。查阅了很多大神写的博客,标题都是类似于这种~~~"彻底弄懂js中的this关键字"等等等,我自认为自己写的这篇博客做不到那么牛逼的程度,所以大家在阅读的过程中如果发现有什么不对的地方可以指正出来一起探讨,总而言之,带着怀疑的态度来看吧,哔哔了这么多废话可以进入主题吧。
this是什么?
this是指包含它的函数作为方法被调用时所属的对象。这句话理解起来感觉还是很拗口的,但是如果你把它拆分开来变成这三句话后就好理解一点了。
1.包含它的函数
2.作为方法被调用时
3.所属的对象
来看个简单的代码压压惊:
function showName(){
console.log(this); //window
}
showName();
参照上面的那三句话来解剖一下这个代码,首先this被showName函数包含了,其次showName()被调用了,最后是被谁调用了呢,我们知道全局定义的函数都是挂载到window对象上面的showName()相当于window.showName();所以this在这里就代表了window。如果还不明白的话我就简单粗暴点讲:
谁特么的调用了我,我就是谁的对象,谁特么的最后调用了我,我就是谁的对象。
继续看代码示例加深理解:
function testFun () {
var name="hello this!";
console.log(this.name);
}
testFun();
嘿嘿嘿,我们分析一下,因为testFun()函数是在全局中被window对象所调用的,那么this久理所当然的是指向window对象了,可是name变量是定义在testFun函数里面的,window对象中并没有定义name变量,当然也就不会打印出"hello this"这个字符串了。
那如果是这样呢?
var name = "hey";
function testFun() {
var name = "hello this!";
console.log(this.name);
}
testFun();
此时定义了一个全局变量name,即在window对象上定义了name,因此会打印出"hey"字符串来。
继续看个稍微复杂一点的:
var obj={
a:"哈哈哈",
b:function(){
var a="嘿嘿嘿";
console.log(this.a);
}
};
obj.b();
this被包含在函数b()中,但是因为是被对象obj所调用的,因此this属于对象obj,所以会打印出字符串"哈哈哈";
我开篇的时候提到谁调用了我,我就属于谁,谁最后调用了我,我就属于谁。大家看下下面这个例子
var obj = {
a:10,
b:{
fn:function(){
console.log(this.a); //undefined
}
}
};
obj.b.fn();
在这个例子中对象obj是在window上面定义的,所以obj.b.fn()=window.obj.b.fn(),那么大家会说this不是被window对象,或者被b调用了吗,请注意此时this最后是被fn锁调用的,所以this属于函数fn,因为在函数fn中并没有定义变量a,所以会打印出undefined;
大家可能还会经常遇到以下几种情况,但是只要牢记我说的那句话就不会又太大的问题。
<div class="box">
<button type="button" id="btn">我是一个按钮</button>
</div>
<script>
var btn=document.getElementById("btn");
btn.onclick=function(){
console.log(this);//btn
}
</script>
this被btn调用所以this属于这个btn按钮对象,看效果图。
接下来我们思考一下this在构造函数中的指向
我们知道构造函数也是一个定义在window上面的函数,,所以构造函数里面的this属于window对象。看代码:
function People(){
var name1="aaa";
this.name2="bbb";
console.log(this);
}
People();
console.log(this.name1);
console.log(name2);
效果图:
因为this是指向window,而name1是定义在局部函数里面因此为undefined,this.name2="bbb";相当于是在window上面声明了一个变量。
上面讲的构造函数都是直接调用的,那如果构造函数是通过new实例化出来的this又会指向谁呢?
function People(){
var name1="aaa";
this.name2="bbb";
console.log(this);
}
var xiaoming=new People();
console.log(xiaoming .name1);
console.log(xiaoming.name2);
效果图:
我们发现this指向了People对象,name1此时为undefined,name2为"bb",这是问什么呢?
这是因为原本的构造函数是window对象的方法,如果不用new操作符而直接调用,那么构造函数的执行对象就 是window,即this指向了window。现在用new操作符后,this就指向了新生成的对象。