解决this指向的输出问题
最近总是遇到这种this指向的题,下面进行分享并进行扩展,希望可以帮助到可能会有困惑的同学。
题目
var User = {
count: 1,
getCount: function(){
console.log(this);
return this.count;
}
};
console.log(User.getCount()); // ?
var func = User.getCount;
console.log(func()); // ?
输出:
解释:
getCount是正常函数,谁调用this就绑定在谁身上(隐式绑定),输出user对象的count属性值1; func = User.getCount只是将地址赋值给了func,在console里执行,这里func相当于一个全局的函数,等于window.func(),window没有count属性,输出undefined;
将getCount函数换成箭头函数
var User = {
count: 1,
getCount: () => {
console.log(this);
return this.count;
}
};
console.log(User.getCount()); // ?
var func = User.getCount;
console.log(func()); // ?
输出:
解释:
箭头函数的this是在声明的时候就绑定了,不能隐式调用,所以User.getCount这样调用,this也不是指向User。它只会从自己的作用域链的上一层继承this。箭头函数的外层如果没有普通函数,那么箭头函数的this就是全局变量window。
扩展一下:建议将一些需要传参并且不作为对象方法使用的函数写作箭头函数会更适合一些
在箭头函数外层套个普通函数
var User = {
count: 1,
getCount:function(){
return() => {
console.log(this)
return this.count;
}
}
};
console.log(User.getCount()()); // ?
var func = User.getCount;
console.log(func()()); // ?
输出:
解释:
注意这里的箭头函数的this指向User并不是因为是User.getCount这种隐式调用才指向的,是从自己的作用域链的上一层继承this,也就是getCount这个普通函数的this,这个普通函数的this就是调用时就指向User啦,所以箭头函数继承了。
箭头函数this输出问题
function fun() {
return () => {
return () => {
return () => {
console.log(this.name)
}
}
}
}
var f = fun.call({ name: 'foo' })
var t1 = f.call({ name: 'bar' })()()
var t2 = f().call({ name: 'baz' })()
var t3 = f()().call({ name: 'qux' })
输出:
解释:
fun是正常函数,调用call方法让this指向{name: 'foo'}对象。箭头函数没有自己的this也并不能使用call,apply以及bind去绑定this,但函数还是会调用的,会自己的作用域链的上一层继承this,所以后面几次的call实际上是失败的,箭头函数一直往上一层寻找name,只会在最外层的fun函数作用域中找到this指向{name: 'foo'}对象的name属性
进阶问题
如果理解了就试试这道题吧!
const User = {
count: 1,
action: {
getCount: () => {
return this.count;
},
},
};
const action = User.action;
const getCount = User.action.getCount;
Promise.resolve().then(() => {
setTimeout(() => {
console.log(action.getCount() + '@@');
});
});
setTimeout(() => {
console.log(User.action.getCount() + '@@@');
});
console.log(getCount() + '@');
输出: 他们的this都指向window噢
关于输出顺序问题有疑惑的可以看搞清async await、微任务,宏任务执行顺序