谈一谈对this指向的理解

122 阅读2分钟

前几天有朋友问,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();