链式调用异步类方法时,this作用域为何及何时发生变化?
为什么.then()调用类方法时会出现this作用域变化?
核心原因:JavaScript的this是调用时绑定
当你执行h.funcOne().then(h.funcTwo)时,你只是把funcTwo函数的引用传递给了then方法。等Promise状态变为resolved后,then内部会直接调用这个函数引用——此时函数的调用上下文不是h实例,而是全局对象(非严格模式)或者undefined(严格模式),自然无法访问到实例上的funcThree和私有属性#asdf。
简单说:h.funcTwo本身只是个函数,脱离了h实例的调用上下文后,this就不再指向h了。
如何避免这种作用域变化?
这里有几种常用方案,按需选择:
1. 调用时用bind绑定this
就是你已经在使用的方式:
h.funcOne().then(h.funcTwo.bind(h))
通过bind强制把funcTwo的this绑定到h实例,无论后续怎么调用这个函数,this都不会变。
2. 用箭头函数包裹调用
箭头函数的this是词法作用域绑定,继承自外层的h实例:
h.funcOne().then(a => h.funcTwo(a))
箭头函数内部不会重新绑定this,直接沿用外层上下文的h,自然能正确访问实例方法。
3. 构造函数中提前绑定方法
在类的构造函数里提前把需要的方法绑定到实例,后续使用时就不用每次bind了:
class Asdf { #asdf; constructor(){ this.#asdf = 'asdf' // 提前绑定this this.funcTwo = this.funcTwo.bind(this) this.funcThree = this.funcThree.bind(this) } async funcOne(){ return this.#asdf } async funcTwo(a){ var x = await this.funcThree(a) return x } async funcThree(a){ return a } }
之后直接传h.funcTwo给then就没问题了。
4. 使用类字段的箭头函数语法
把类方法直接定义为箭头函数,利用箭头函数的词法this绑定特性:
class Asdf { #asdf; constructor(){ this.#asdf = 'asdf' } async funcOne(){ return this.#asdf } // 用箭头函数定义方法 funcTwo = async (a) => { var x = await this.funcThree(a) return x } funcThree = async (a) => { return a } }
这种方式下,funcTwo和funcThree的this永远指向类实例,不管怎么传递引用都不会失效。
内容的提问来源于stack exchange,提问作者Koza
相关产品推荐
相关产品推荐

