为什么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都有个函数对象做属性.
附老外原文: