前言
关于 this 指向问题,网上的资料很多,面试问的也很多,似懂非懂的人也很多。
有人觉得女生的心思很难猜,也就有人觉得 this 的指向问题比女生的心思更难猜。
女生的心思其实很简单 —— 希望不猥琐的你用心去关注她(和帅没有很大关系,当然帅加分)。
this 的指向问题也不难 —— 谁调用就指向谁。
到底谁是调用者
结论先行:this 的指向是谁调用就指向谁;即调用之前,this 还不知其指向。
讨论谁是调用者之前先说 this 的作用:
this 是函数内部两个特殊对象之一,拥有这个对象可以改变显式传递的弊端,即可将函数定义的更加简洁和易于复用。
接下来重点讨论谁是调用者
var name = '小生方勤';
function consoleName() {
console.log(this.name);
}
var test = {
name: '方小勤',
method: function() {
consoleName();
}
};
test.method();
上面这个笔试题相信你已经有了答案,现在可以带着你刚才的思考切入下面的解释。
四种情况的调用
想知道 this 指向就需要找到调用者。有人认为调用者并不好确定,其实大体只有四种情况,我一一介绍。
直接调用的默认绑定, this 指向一定是全局对象(浏览器的话是 window)。在严格模式下其值会是
undefined
。对象调用的隐式绑定, this 指向就是这个调用的对象。
call()/apply() 方式的显式绑定, this 指向传入的对象。
new 方式的绑定规则, this 指向这个构造出的新对象。
第一种 & 第二种:
let name = '小生方勤';
function consoleName() {
console.log(this.name);
}
let test = {
name: '方小勤',
method: function() {
console.log(this.name); // 方小勤
consoleName(); // 小生方勤
}
};
test.method();
开头题目的答案就在这里。
虽然 test.method()
的调用方式使 method
内部使用的 this 会指向 test
,但实际调用的是 - 直接调用 consoleName()
;所以 this 的指向还是全局对象 window。
所以输出的是:
通过这个例子,你对第一种和第二种的绑定方式应该就懂了。
第三种:
let name = '小生方勤';
let test = {
name: '方小勤',
method: function() {
console.log(this.name);
}
};
test.method.apply(window); // '小生方勤'
隐式绑定和显式绑定一起使用的时候,显式绑定的优先级更高。
第四种:
function consoleName(name) {
this.name = name;
}
let useNname = new consoleName('小生方勤');
console.log(useNname.name) // 小生方勤
通过这个例子想必你对 new 方式中 this 的指向问题也明白了,即构造函数(consoleName)中的 this 会绑定到实例(useNname)上。
优先级
关于优先级我画了一张图直观的来说明这个问题:
箭头函数补充
箭头函数比较特殊,不受上面四条规则的约束。箭头函数的 this 根据外层函数确定。
而且箭头函数的 this 一旦被绑定,就无法改变。
思考题
以下代码输出什么,原因是什么?欢迎评论区留言。
function consoleName() {
return (name) => {
console.log(this.name);
}
}
let testOne = {
name: '小生方勤',
};
let testTwo = {
name: '方小勤',
};
let text = consoleName.call( testOne );
text.call( testTwo );
参考
《JavaScript 高级程序设计》
《你不知道的 JavaScript》上
NOT THE END
该系列首发于同名公众号【小生方勤】,扫码关注即可订阅(可进交流群)。
彩蛋:你若发现这个系列文章有错别字,每个字 5 元红包的有偿纠正费(只限最早告知我的读者[微信号:wqhhsd])。
转载:https://blog.csdn.net/weixin_39843414/article/details/101443790