this指向大致可以分为两种,一种是ES5中的this,另外一种是ES6中的this也就是箭头函数的this。
想要了解ES5中的this只要记住两点就可以了:
this的指向在函数执行时才能确定, 而this指向 最近一次 调用的对象(不过也有几种特殊情况,后面会做说明。)
来看几个例子
var n = 10;
var obj = {
n: 20,
fn: function(){
console.log(this.n)
}
}
obj.fn(); // 20
函数fn是通过obj.fn()执行的 所以this指向obj
var obj1 = {
n: 30,
o: {
n: 40,
fn: function(){
console.log(this.n)
}
}
}
obj1.o.fn(); // 40
这里的obj1也是调用者之一可是最后并没有输出30 是因为this指向的时最近一次调用的对象,也就是o,但是有一种特殊情况 如下
var obj1 = {
n: 30,
o: {
n: 40,
fn: function(){
console.log(this.n) //undefined
console.log(this) //window
}
}
}
var func = obj1.o.fn;
func();
这里的this又指向了window 很奇怪对不对? 这是因为把obj1.o.fn赋值给了全局变量func (并没有执行,所以this还不能确定)而func的执行者是window 所以this又指向了window 这也印证了本文开头的说法:this只有在 执行时 才确定,而this指向 最近一次 调用的对象
有一种隐式调用的情况很容易让人混淆。
function test(){
var name = 'tom';
console.log(this.name); //undefined
console.log(this); //window
}
test();
这里乍一看好像并没有某个对象调用test方法,实际上这是一种隐式调用。真正的调用者是全局对象window, 相当于 window.test(); 所以这里的this指向window ,类似的场景还有setTimeout回调、匿名函数自调
function test(){
setTimeout(function(){
console.log(this) //window
},100)
}
test(); //这次this出现在全局函数setTimeout()中的匿名函数里,并没有某个对象显示的调用这个匿名函数,所以this指向window对象
(function(){console.log(this)})() //window
还有一种特殊情况值得关注:当this遇上return
function test(){
this.name = 'jack';
return {};
}
var t = new test();
t.name // undefined
function test(){
this.name = 'jack';
return;
}
var t = new test();
t.name // jack
这是怎么回事呢? 原因是当this遇上return时 如果return的是一个对象那么this指向这个return的对象,否则this仍然指向t函数的实例。有一个例外是:
function test(){
this.name = 'jack';
return null;
}
var t = new test();
t.name; //jack
null是一个对象但是this仍然指向函数的实例!!!
箭头函数中的this
箭头函数中的this在函数定义时绑定,而不是在函数执行时绑定! 这和ES5中的定义恰恰相反。来看几个例子
var obj = {
name: 'jack',
fn: function(){
console.log(this)
}
}
obj.fn(); //obj
这里是ES5的写法 this指向obj
var obj = {
name: 'jack',
fn: ()=>{
console.log(this)
}
}
obj.fn(); //window
为什么箭头函数中的this指向了window了呢? 原因就是this是继承自父执行上下文中的this 比如这里的箭头函数中的this,箭头函数本身所在的对象为obj,而obj的父执行上下文就是window
总觉得写的不够透彻和全面,保存到草稿一个月后因为要写新博客才发布出来。多多指正吧!