为什么我的ES6(使用Babel)类说`this`在实例方法中是未定义的?

我使用Hapi.JS在Node中构build应用程序。

我有一个authentication插件的类,给我各种各样的问题。 当我试图从类的方法中引用this ,我得到一个错误,说this是未定义的。 为什么发生这种情况?

摘录:

 class OAuth { constructor () {} register (server, err, next) { this.server = server; this.registerRoutes(); } registerRoutes () { console.log(this.server.route); this.server.route([ { method: 'POST', path: '/oauth/token', config: { auth: false, handler: function(request,reply){ console.log("test"); reply("test"); } } }, { method: 'GET', path: '/test', config: { auth: false, handler: function(request,reply){ console.log("test"); reply("test"); } } } ]); } } module.exports = new OAuth(); 

在其他地方,这被称为:

 const oauth = require('./oauth'); oauth.register(server); 

每次调用注册函数时,都会收到此错误:

 TypeError: Cannot set property 'server' of undefined 

为什么在我的实例不工作?

ES6类与巴贝尔不自动绑定this给你。 自引入class以来,这是一个常见的误解。 有多种方法来解决它。

  1. 使用ES7。 Babel有一个实验(截至这篇文章) 类属性插件。

     class OAuth { constructor () {} register = (server, err, next) => { this.server = server this.registerRoutes() } registerRoutes = () => {} } 

这个怎么用? 当你使用arrow-functions和class-properties插件的时候,它会被转换成如下所示的types,按照你所期望的那样使用class语法进行绑定。

 var OAuth = function OAuth() { var _this = this; _classCallCheck(this, OAuth); this.register = function (server, err, next) { _this.server = server; _this.registerRoutes(); }; this.registerRoutes = function () {}; } 
  1. 在构造函数中绑定您的类属性

     class OAuth { constructor () { // `this` is the OAuth instance in the constructor this.register = this.register.bind(this) this.registerRoutes = this.registerRoutes.bind(this) } register (server, err, next) { // `this` is the global object.. NOT! // after binding in the constructor, it's the OAuth instance ^_^ // provided you use `new` to initialize your instance this.server = server this.registerRoutes() } registerRoutes () {} } 
  2. 从反应中使用createClass ,它为你做绑定。 请注意,我们只对其类属性绑定魔法使用反应。 我们不是创build反应组件。

     import React from 'react' const OAuth = React.createClass({ register (server, err, next) { this.server = server this.registerRoutes() } registerRoutes () {} }) 
  3. 只使用反应级别的 autoBind 。 在这里,我们使用ES6 +类语法来创build反应组件,只是使用autoBind方法。 我们不必使用与反应组件一起提供的componentWillMountrender等。

     import { autoBind } from 'react-class' class OAuth extends React.Component { constructor(props) { super(props) autoBind(this) } register (server, err, next) { this.server = server this.registerRoutes() } registerRoutes () {} } 
  4. 滚动你自己的类属性联编程序。 这是一个很好的练习,基本上和选项2一样,可能更less的代码。

     // call it in your constructor bindStuff(this, ['register', 'registerRoutes', 'etc']) // define it somewhere as function bindStuff (context, props) { props.forEach(prop => { context[prop] = context[prop].bind(context); }) } 
  5. 如果你真的想创build反应组件,你可以组合箭头函数和属性初始值设定项来做类似的事情

     class OAuthComponent extends React.Component { whateverMethodYouWant = (event) => { this.setState({somePropertyYouCareAbout: true}) // this is bound } anotherMethod = () => { this.whateverMethodYouWant() // this is bound } }