在Javascript类内部引用类成员是否有更简便的实现方式?
JS类this指向优化方案
首先纠正一个认知误区
你示例代码里的let me = this是完全多余的:普通的分支判断、循环语句不会改变this的上下文指向。只要loadExternalData是通过类实例调用的,方法内部的this始终指向当前实例,if块里可以直接用this.loadJSON、this.loadHTML,不需要额外存变量。
只有当你在方法内部使用普通函数作为回调(比如setTimeout的回调、Promise的then回调、事件监听回调)时,才会出现this指向变更的问题。
常用的this指向固定方案
如果确实是回调场景下需要固定this,有几种比存me/that更优雅的写法,符合现代JS开发规范:
1. 回调使用箭头函数
箭头函数不会绑定自身的this,会直接继承外层作用域的this指向,适合临时回调场景:
loadExternalData() { const filePath = `${this.dataDirectory}${this.currentDoc.filepath}`; const dataIsJson = this.currentDoc.filepath.includes('.json'); // 异步回调场景直接用箭头函数,不需要存this fetch(filePath).then(res => { if (dataIsJson) { this.loadJSON(res); } else { this.loadHTML(res); } }) }
2. 类方法定义为箭头函数属性
如果希望方法无论在什么场景下调用(比如作为事件回调传递给其他模块),this都固定指向当前实例,可以直接把方法定义为类的箭头函数属性:
class Catalogue { constructor () { this.currentDoc = null; this.dataDirectory = "data/"; } loadJSON = (filepath) => { // 业务逻辑 } loadHTML = (filePath) => { // 业务逻辑 } loadExternalData = () => { const filePath = `${this.dataDirectory}${this.currentDoc.filepath}`; const dataIsJson = this.currentDoc.filepath.includes('.json'); // 全程直接用this,不需要额外存储 dataIsJson ? this.loadJSON(filePath) : this.loadHTML(filePath); } }
这是目前前端开发中最常用的类this固定方案,写法简洁,没有额外冗余代码。
3. 方法开头解构属性(可选)
如果不想每次都写this.,可以在方法开头把需要用到的实例属性解构出来:
loadExternalData() { const { dataDirectory, currentDoc, loadJSON, loadHTML } = this; const filePath = `${dataDirectory}${currentDoc.filepath}`; const dataIsJson = currentDoc.filepath.includes('.json'); // 调用方法时绑定this即可 dataIsJson ? loadJSON.call(this, filePath) : loadHTML.call(this, filePath); }
该方案适合单个方法内需要用到大量实例属性的场景,能减少重复的this.书写。
重构建议
现有代码不需要大规模重构:
- 先删除所有非必要的
me/that临时变量 - 回调场景替换为箭头函数,需要固定方法this的改为类箭头属性即可
另外要说明:JS的语言设计就是需要通过this访问实例属性,这个和你熟悉的其他面向对象语言的this本质上没有区别,只是JS的this是动态绑定的,用上述方案就能规避99%的this指向问题。
内容的提问来源于stack exchange,提问作者Zac
相关产品推荐
相关产品推荐

