这是我参与8月更文挑战的第16天,活动详情查看8月更文挑战
前言
学习 JavaScript,离不开 this,今天我们就来聊聊 this,看看你是否对 this 有足够的了解。那我们开始吧。
this 执行主体,谁把它执行的「和在哪创建&在哪执行都没有必然的关系」。this 有五种情况,下面逐一举例,结合例子来熟悉。
函数执行,看方法前面是否有“点”
函数执行,看方法前面是否有“点”,没有“点”,this 是 window「严格模式下是 undefined」,有“点”,“点”前面是谁,this 就是谁。
我们看个例子:
const fn = function fn() {
console.log(this);
}
let obj = {
name: '追梦玩家',
fn: fn
};
fn(); // window
obj.fn(); // {name: "追梦玩家", fn: ƒ}
给当前元素的某个事件绑定方法
给当前元素的某个事件绑定方法,当事件行为触发,方法中的 this 是当前元素本身「排除 attachEvent」。
下面的代码给 document.body 绑定事件,当点击事件被触发的时候,打印出来就是 document.body
document.body.addEventListener('click', function() {
console.log(this);
})
构造函数中的 this 是当前类的实例
我们看下下面代码的输出结果,是什么?
function Factory() {
this.name = '追梦玩家';
this.age = 18;
console.log(this);
}
let f = new Factory(); // {name: "追梦玩家", age: 18}
箭头函数
箭头函数中没有执行主体,所用到的 this 都是其所处上下文的 this。要怎么理解呢?
let demo = {
name: 'DEMO',
fn() {
console.log(this); // {name: "DEMO", fn: ƒ}
setTimeout(function() {
console.log(this); // window
}, 1000);
setTimeout(() => {
console.log(this); // {name: "DEMO", fn: ƒ}
}, 1000);
},
}
demo.fn();
从上面的例子,我们可以看出箭头函数的 this,其实就是所在上下文的 this,也就是例子中的 demo 对象。
call/apply/bind
其实就是基于 Function.prototype 上的 call/apply/bind 方法去改变 this 指向。
来个例子:
function func(x, y) {
console.log(this, x, y);
}
let obj = {
name: '追梦玩家'
};
func.call(obj, 10, 20);
func.apply(obj, [10, 20]);
document.body.addEventListener('click', func.bind(obj, 10, 20));
输出结果都为 {name: "追梦玩家"} 10 20
我们来看看,为什么输出结果都是这个样子?
其实可以简单理解,因为 obj 对象没有 func 这个方法,所以借用 func 这个方法,func 函数自身没有 call 方法,所以会基于 __proto__ 找到 Function.prototype.call,把 call 方法执行,在 call 方法内部 「call 执行的时候」 call(context->obj,...params->[10,20])。
call 方法的原理:
- 把 func 中的 this 改为 obj
- 并且把 params 接收到的值当做实参传递给 func 函数
- 并且让 func 函数立即执行
知道 call 方法的原理,其实我们就可以自己手写一下 this。大家可以尝试写一下。
apply 和 call 的第一个参数都是 this,区别在于通过 apply 调用时实参是放到数组中的,而通过 call 调用时实参是逗号分隔的。
bind 方法的原理:
- 和 call/apply 的区别,并没有把 func 立即执行
- 把传递进来的 obj/10/20 等信息存储起来「闭包」
- 执行 bind 返回一个新的函数,例如:proxy,把 proxy 绑定给元素的事件,当事件触发执行的时候是返回的 proxy
- 在 proxy 内部,再去把 func 执行,把 this 和值都改变为之前存储的那些内容
总结
- this 的五种情况分析
- this 执行主体,谁把它执行的「和在哪创建&在哪执行都没有必然的关系」
- Q1:函数执行,看方法前面是否有“点”,没有“点”,this 是 window「严格模式下是 undefined」,有“点”,“点”前面是谁,this 就是谁
- Q2:给当前元素的某个事件绑定方法,当事件行为触发,方法中的 this 是当前元素本身「排除 attachEvent」
- Q3:构造函数中的 this 是当前类的实例
- Q4:箭头函数中没有执行主体,所用到的 this 都是其所处上下文的 this
- Q5:可以基于 Function.prototype 上的 call/apply/bind 去改变 this 指向
文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你或者喜欢,欢迎点赞和关注。