为什么class中箭头函数定义的属性, this指向一直是instance

今天被React的class component中handler中的this指向所困扰. 具体而言, 搞不懂为何下列代码的this指向instance

 1   class FooClass {
 2     constructor(a) { this.a = a;  }
 3     xyz = () => { console.log(this); }
 4     pqr() { console.log(this); }
 5   }
 6 
 7   const obj = new FooClass('n') 
 8   obj.xyz() // FooClass { xyz: [Function: xyz], a: 'n' }
 9   obj.pqr() // FooClass { xyz: [Function: xyz], a: 'n' }
10   const a = obj.pqr
11   a() //undefined
12   FooClass.prototype.pqr() // {}, 其实是FooClass.prototype

第7行的this为啥指向instance呢?

按理说, arrow function的this指向lexical context的this, 但class FooClass里也没this呀...

直到看到老外的文章, 发现这是由于js engineer将class代码转换成function代码的原因. 即, 以上class代码, 转为function代码后, 为 

function FooClass(a) {
  this.a = a;
  this.xyz = () => {
    console.log(this.a);  //原来this获得的是这个lexical context的this
  }
}

FooClass.prototype.pqr = function () {
  console.log(this.a); //所以这里的this指向谁, 需要动态绑定
}

因此

class FooClass {
  constructor(a) {this.a = a;}

  // 写在这里, 相当于就写在constructor里. 成为instance的属性
  xyz = () => {console.log(this.a);}

  // 写在这里, 会成为FooClass.prototype属性
  pqr() {console.log(this.a);}
}

 

ps, 看来, 各个handler, 还是以函数声明的形式写比较好, 因为它就会放在prototype上一份, 而不是每个instance上都放一份. handler调用时, 写成 event=>this.handler(...)即可, this依然指向instance. 总之, 这样减少了instance的体积, 不用每个instance都有个函数对象做属性.

 

附老外原文:

https://medium.com/@sanjuctab/arrow-functions-the-this-keyword-and-classes-in-javascript-a80a2f55e85a

 

posted @ 2023-03-13 07:37  mayingdts  阅读(39)  评论(0编辑  收藏  举报