前几天有朋友问,this的指向问题,一时间不知道从何说起,痛定思痛,决定重新学习一下,总结以下的一些场景,此处做个笔记,有问题的话,希望有大佬能指正。。。。
一般来说,this的应用场景有五种(重点讲一下bind/apply/call):
1.使用Function.prototype上的bind/apply/call去改变this指向,这里我重写了一下三个函数的方法,可以更加清晰的理解三个方法,如下
Function.prototype.call = function call(context, ...params) {
let self = this,
key = Symbol('KEY'),
result;
context == null ? context = window : null;
!/^(object|function)$/i.test(typeof context) ? context = Object(context) : null;
context[key] = self;
result = context[key](...params);
delete context[key];
return result;
};
这里其实就是利用 “.”定this(也就是第三个场景),apply的方法就类似call方法,只需要把接受的参数改为数组即可,这里不做赘述
Function.prototype.bind = function bind(context, ...params) {
let self = this;
return function proxy(...args) {
// 把func执行并且改变this即可 args->是执行proxy的时候可能传递的值
self.apply(context, params.concat(args));
};
};
bind方法则是通过闭包,把传递进来的参数信息存储起来,并且,与apply与call不同是,bind并不会立即执行方法,并且执行bind后,会返回一个新的方法,如上面的proxy,把proxy绑定给元素的事件,当事件触发执行的是返回的proxy,在proxy内部,再去把方法执行,把this和值都改变为之前存储的那些内容,如下:
document.body.addEventListener('click', func.bind(obj, 10, 20));
document.body.addEventListener('click', proxy)
2.构造函数体中的this是当前类的实例
function Factory() {
this.name = '小明';
this.age = 24;
this.birthDay= '2020.6.6'
console.log(this);
}
let f = new Factory;
3.给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的this是当前元素本身「排除attachEvent」
document.body.addEventListener('click', function () {
console.log(this);
});
4.看方法前面是否有“点”,没有“点”,(ps:this是window,但是严格模式下是undefined),有“点”,“点”前面是谁this就是谁
const fn = function fn() {
console.log(this);
};
let obj = {
name: 'OBJ',
fn: fn
};
fn();
obj.fn();
5.箭头函数中没有执行主体,所用到的this都是其所处上下文中的this
let demo = {
fn() {
console.log(this);
setTimeout(function () {
console.log(this);
}, 100);
setTimeout(() => {
console.log(this);
}, 100);
}
};
demo.fn();