一、前言
JavaScript中this根据所处的执行环境不同而有所不同;听上去好像一头雾水,但是只要找到关键点——执行环境,或者通俗一点说就是被谁调用,你就能很容易的理解它,下面通过几个方面来具体说明:
二、this 的几种情况
1. 全局环境
//案例1
var a=function(){
console.log(this);//Window
};
a();
//案例2
var a=function(){
console.log(this);//Window
return function(){
console.log(this);//Window
}
};
a()();
说明:
案例1:a函数的执行环境是全局,a()可以理解为是window.a(),即被window对象调用,所以this指向window。
案例2:此案例可能稍微有点复杂,似乎看不到到底谁在调用,可以变形一下,var x=a();x();这时候的x的执行环境也是全局,故this也指向window。
2. 对象环境
var a={
print:function(){
console.log(this); //对象a
};
}
a.print();
说明:以上print()方法是由a调用的,所以this指向的就是a这个对象,可在函数体内通过this===a来判断。
3. call、apply、bind方法绑定this
var a={
printA:function(){
console.log(this); //对象b,因为通过call将this指向b对象
}
};
var b={
printB:function(){
console.log(this);//对象a,因为通过call将this指向a对象
}
};
a.print.call(b);
b.print.call(a);
说明:call、apply、bind方法才是最好理解的this,将那个对象绑定进去,函数体里面的this就指向哪个对象。顺便简单说说三者的区别:
call:第一个参数绑定this,后面的参数顺着排,立即调用。
apply:第一个参数绑定this,后面的参数放在数组内,立即调用。
bind:第一个参数绑定this,后面的参数顺着排,不立即调用。
4. 构造函数环境
var A = function(name){
this.name = name;
console.log(this)//b这个实例对象,{name:'wxp'};
};
var b = new A('wxp');
console.log(b);//{name:'wxp'};
说明:记住所有的构造函数内的this指向的都是构造函数的实例对象。想要知道为什么,看看下面模拟的new操作符。
//1.创建一个空对象obj;
//2.调用构造函数并将this指向obj;
//3.返回obj;
function imitateNew(sup){
var obj = {};
sup.call(obj);//这里通过call把this指向了obj这个对象
obj.__proto__= sup.prototype;
return obj;
}
5. 箭头函数
var a={
print:function(){
return ()=>{
console.log(this);//指向a对象
}
}
};
a.print()();
说明:箭头函数中的this指的是外层代码块的this,以上案例在print函数作用域内this指向的就是a这个对象。
三、思考
var a={
print:()=>{
return ()=>{
console.log(this);//指向?
}
}
};
a.print()();
可以思考一下,以上 this 会输出什么,为什么?