JavaScript类中forEach内this指向异常的解决方法咨询
解决JavaScript Class中forEach循环内无法访问实例变量的问题
嘿,这个问题我之前也踩过坑!正如你推测的那样,问题出在forEach回调函数里的this指向不对——普通函数作为回调时,this会绑定到forEach的执行上下文,而不是你的Debugger类实例,所以才会报Cannot read property 'appList' of undefined。
下面给你几种靠谱的解决方式:
方法1:使用箭头函数(最简洁)
箭头函数不会绑定自己的this,它会继承外层作用域的this,也就是processApps方法里的类实例。修改forEach的回调为箭头函数就行:
class Debugger { constructor(){ this.appList = []; this.getApps().then(this.processApps); } getApps(){ return new Promise((resolve, reject) => { System.getAllApplications(function (applicationInfoList) { resolve(applicationInfoList); }); }); } processApps(apps){ apps.forEach(app => { // 改成箭头函数 this.appList.push(new Application(app.uuid)); }); } }
方法2:提前保存this到变量
在processApps方法开头,把当前实例的this存到一个变量(比如self或者that),然后在回调里用这个变量访问实例属性:
class Debugger { constructor(){ this.appList = []; this.getApps().then(this.processApps); } getApps(){ return new Promise((resolve, reject) => { System.getAllApplications(function (applicationInfoList) { resolve(applicationInfoList); }); }); } processApps(apps){ const self = this; // 保存实例的this apps.forEach(function(app){ self.appList.push(new Application(app.uuid)); // 用self代替this }); } }
方法3:利用forEach的第二个参数指定this
forEach方法本身支持第二个参数,用来指定回调函数执行时的this值,直接把类实例传进去就行:
class Debugger { constructor(){ this.appList = []; this.getApps().then(this.processApps); } getApps(){ return new Promise((resolve, reject) => { System.getAllApplications(function (applicationInfoList) { resolve(applicationInfoList); }); }); } processApps(apps){ apps.forEach(function(app){ this.appList.push(new Application(app.uuid)); }, this); // 传入this,指定回调的this为类实例 } }
方法4:在构造函数中绑定processApps的this
如果担心后续processApps被其他地方调用时this跑偏,可以在构造函数里用bind把它的this固定为类实例:
class Debugger { constructor(){ this.appList = []; this.processApps = this.processApps.bind(this); // 绑定this this.getApps().then(this.processApps); } getApps(){ return new Promise((resolve, reject) => { System.getAllApplications(function (applicationInfoList) { resolve(applicationInfoList); }); }); } processApps(apps){ apps.forEach(function(app){ this.appList.push(new Application(app.uuid)); }); } }
这几种方法都能解决问题,个人最推荐箭头函数的写法,简洁又直观!
内容的提问来源于stack exchange,提问作者Ryan Peterson
相关产品推荐
相关产品推荐

