2016-03-06 91 views
2

我知道(我认为)ES6中的箭头功能使用Lexical this,但我不确定为什么fat arrow功能调用的函数将this设置为undefined。如何在由ES6箭头函数调用的函数中使用`this`?

我需要做些什么才能拨打this.setResulthandleAuthResult?如果我不需要,我不想使用旧的function() {}.bind(this)

"use strict"; 

class Example { 
    constructor() { 
     this.checkAuth(); 
    } 

    checkAuth() { 
     document.write("Checking auth now. "); 
     var iid = setInterval(() = > { 
      if (true) { // Have to do some dumb check here 
       clearInterval(iid); 
       this.authenticate(this.handleAuthResult) 
      } 
     }, 500); 
    } 

    authenticate(callback) { 
     callback({ 
      value: true 
     }); 
    } 

    handleAuthResult(result) { 
     document.write(`The result is ${result.value}.`); 
     this.setResult(result, this.loadThePage) 
     //^`this` is undefined here. How can I ever set the result? 
    } 

    // Another asynchronous thing 
    setResult(result, callback) { 
     callback(); 
    } 

    loadThePage() { 
     document.write("The code never gets here, but the page should load now. "); 
    } 
}; 
var example = new Example(); 

谢谢! https://jsfiddle.net/vujev4dj/

编辑:在我的这种防御被标记为重复的行为我期待做下面小提琴,这就是为什么我预计不会有ES6使用bind功能上this.handleAuthResult工作: https://jsfiddle.net/m9e7j4ds/

+0

它在拨弄工作的原因是因为它使用'React.createClass()',而不是使用ES6类(延伸'React.Component') 。 'React.createClass()'绑定所有方法,这在使用ES6类时不会发生。 – ArneHugo

+0

@bergi我不同意这是你链接的问题的重复,因为它不是将方法绑定到ES6类实例的方法。尤其是,在答案中没有提及直接制作一个箭头功能。我相信这是提问者正在寻找的东西,尽管问题可能会更好地提出。 – ArneHugo

回答

0

this是在handleAuthResultundefined因为handleAuthResult不是箭头功能,因此不具有词法this。这是一个正常的原型函数(松散地,“方法”),这意味着this是由它的调用方式定义的。

你调用它的方式:

authenticate(callback) { 
    callback({ 
     value: true 
    }); 
} 

不设置this具体的东西,所以thisundefined(因为你在严格模式下是)。

为了解决这个问题,必须通过thisauthenticate,并使用它:

this.authenticate(this.handleAuthResult, this) 

authenticate(callback, thisArg) { 
    callback.call(thisArg, { 
     value: true 
    }); 
} 

或使用Function#bind创建,调用它时,会调用handleAuthResult用正确的函数this

this.authenticate(this.handleAuthResult.bind(this)) 

或出于完整性考虑,naomik points out a third option which is quite elegant:使用另一个箭头功能:

this.authenticate(() => this.handleAuthRequest()) 
+1

我看到你也在这里附加@ naomik的解决方案。你的回答总体上非常简洁,解释了我为什么感到困惑。我接受了你的回答:) –

0

checkAuth,你应该使用

this.authenticate(this.handleAuthResult.bind(this))

这是因为,当CA灌装callback({value: true});有没有this绑定

+0

另一种方法是将回调方法定义为箭头函数,当应用于类时,它们总是与它们所在的类绑定。这个问题具体询问有关箭头功能。 – ArneHugo

4

当你调用

this.authenticate(this.handleAuthRequest); 

this变得失去

你可以做

this.authenticate(this.handleAuthRequest.bind(this)); 

或者

this.authenticate(() => this.handleAuthRequest()); 

总的来说,代码非常凌乱,很多部分对我来说没有任何意义。具体callback({value: true})是很奇怪的。无论如何,如果您有更具体的问题,我很乐意提供帮助。

+1

关于使用另一个箭头功能的第三个选项的好处。 –

+0

非常感谢您的建议。我同意代码很混乱,但它实际上是Google提供的这个JavaScript快速入门的超级简化版本,我用我自己的函数替换了它们的函数,并使用了回调函数:https://developers.google.com/google-apps/calendar/quickstart/js#step_1_turn_on_the_api_name –

+1

谢谢@TJ。我通常更喜欢使用另一个箭头函数,而不是靠'Function.prototype.bind' – naomik

相关问题