Angular 2中setTimeout内this指向异常:this.Data未定义报错
解决
TypeError: undefined is not an object (evaluating 'this.Data')问题 这个错误的核心原因是**setTimeout回调函数里的this指向发生了改变**,不再指向你的组件实例,导致无法访问到注入的DataProvider实例。尤其是在forEach循环和switch语句的嵌套场景下,这个指向问题会更突出。
下面给你几种可行的解决方案,按推荐程度排序:
1. 使用箭头函数(最推荐)
箭头函数会自动继承外层作用域的this,所以在setTimeout的回调里用箭头函数,就能直接拿到组件实例的this,自然可以访问this.Data。
结合你的代码修改示例:
initiateStepActions(){ const actionsToTake = this.items[this.currentStep]['timed_actions']; if (actionsToTake){ // 用箭头函数作为forEach的回调,保证this指向不变 actionsToTake.forEach(action => { setTimeout(() => { // 这里用箭头函数 switch(action['ac']) { // 假设你的action类型字段是'ac' case 'someAction': // 现在this指向组件实例,可以正常访问this.Data console.log(this.Data.xmldata); break; // 其他case逻辑 } }, action['delay']); // 假设你的延迟字段是'delay' }); } }
2. 提前保存this到变量
如果你的项目需要兼容ES6之前的环境,可以在forEach外层先把组件实例的this保存到一个变量(比如self/that),然后在回调里用这个变量代替this:
initiateStepActions(){ const self = this; // 保存当前组件实例的this const actionsToTake = this.items[this.currentStep]['timed_actions']; if (actionsToTake){ actionsToTake.forEach(function(action) { setTimeout(function() { switch(action['ac']) { case 'someAction': // 用self代替this,访问DataProvider console.log(self.Data.xmldata); break; } }, action['delay']); }); } }
3. 使用bind()绑定this
你也可以给setTimeout的回调函数绑定组件实例的this,强制改变它的指向:
initiateStepActions(){ const actionsToTake = this.items[this.currentStep]['timed_actions']; if (actionsToTake){ actionsToTake.forEach(action => { setTimeout(function() { switch(action['ac']) { case 'someAction': console.log(this.Data.xmldata); break; } }.bind(this), action['delay']); // 绑定组件实例的this }); } }
额外提醒
在类的方法中,普通函数作为回调(比如forEach、setTimeout的回调)时,this默认会指向全局对象(浏览器中是window,Node.js中是global),而不是类的实例。箭头函数完美解决了这个问题,因为它没有自己的this,会沿用外层上下文的this,所以现在大部分现代项目都会优先使用箭头函数来处理这类场景。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

