美文网首页
一道题讲明白JavaScript中this的指向和闭包

一道题讲明白JavaScript中this的指向和闭包

作者: HolidayPeng | 来源:发表于2018-12-26 09:40 被阅读15次
class A {
    constructor() {
        this.b = 1;
    };
    c() {
        console.log(this.b);
    };
    d() {
        setTimeout(this.c, 1000);
    };
const a = new A();
a.d(); // undefined

在构造函数A中,定义了属性b,赋值为1。在A的原型链上定义了方法c和方法d,方法c打印属性b,方法d设置定时器,1秒后调用方法c。实例化A保存到a, 调用实例中的d方法,输出undefined。

在构造函数中,将c方法直接作为回调传入定时器,此时c方法并未执行,而是在实例a调用d方法的时候在定时器内部执行的,此时定时器的执行环境上下文是window,在全局中并未定义c,所以为undefined;
如果需要在调用的时候能在实例中找到c,有三种办法:

一、用闭包将this保存起来:
首先什么是闭包?一句话:在一个函数内部return一个函数,被return的这个函数引用了外面那个函数中定义的变量,导致这个变量永远不会被销毁,也不会被改变:

function closure() {
  var canNotBeChangedByContext = 1;
  return function(arg) {
    console.log(canNotBeChangedByContext += arg);
  };
};
closure()(5); //6
closure()(5); //6

当然也有办法可以破解,将该函数赋值给一个变量保存起来,再连续调用那个变量即可:

function closure(){
  var canNotBeChangedByContext = 1;
  return function(arg){
    console.log(canNotBeChangedByContext += arg);
  };
};
var breakClosure = closure();
breakClosure(5); // 6
breakClosure(5); // 11

理解了什么是闭包,我们就可以在c方法中,通过闭包,将this永久地保存起来,供下面被return的函数引用,不论它是在什么样的执行环境:

class A {
    constructor() {
        this.b = 1;
    };
    c() {
        const self = this;
        return function() {
              console.log(self.b);
         }
    };
    d() {
       setTimeout(this.e(), 1000)
    }
};
const a = new A();
a.d(); // 1

二、用箭头函数:
箭头函数没有像function关键字的函数那样,它不会根据执行环境而改变this的指向,在定义的时候取到的this是什么,就不会再改变。

class A {
    constructor() {
        this.b = 1;
    };
    c() {
        console.log(this.b);
    };
   
    d() {
        const self = this;
        setTimeout(() => console.log(this.b), 1000);
    };
};
const a = new A();
a.d(); // 1

三、用Function的bind方法:
在调用bind方法的时候,重新创建了一个函数,且该函数的this指向已被设置为传入bind方法的第一个参数。这里我们传的是this,所以当这个新的函数在计时器里被调用的时候,取到的this是已经被保存的this,指向该构造函数的实例。

class A {
    constructor() {
        this.b = 1;
    };
    c() {
        console.log(this.b);
    };
   
    d() {
        const self = this;
        setTimeout(this.c.bind(this), 1000);
    };
};
const a = new A();
a.d(); // 1

相关文章

网友评论

      本文标题:一道题讲明白JavaScript中this的指向和闭包

      本文链接:https://www.haomeiwen.com/subject/xedakqtx.html