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

Bre*_*nan 11 javascript node.js ecmascript-6 hapijs babeljs

我正在使用Hapi.JS在Node中构建应用程序.

我有一个认证插件的类,它给了我各种各样的问题.当我尝试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();
Run Code Online (Sandbox Code Playgroud)

在其他地方,这被称为:

const oauth = require('./oauth');
oauth.register(server);
Run Code Online (Sandbox Code Playgroud)

每次调用寄存器函数时,都会收到此错误:

TypeError: Cannot set property 'server' of undefined
Run Code Online (Sandbox Code Playgroud)

为什么我的实例不起作用?

cre*_*dle 13

带有babel的ES6课程不this适合你.这是自class引入以来常见的误解.有多种方法可以解决它.

  1. 使用ES7.Babel有一个实验性的(截至本文)class-properties插件.

    class OAuth {
      constructor () {}
    
      register = (server, err, next) => {
        this.server = server
        this.registerRoutes()
      }
    
      registerRoutes = () => {}
    }  
    
    Run Code Online (Sandbox Code Playgroud)

这是如何运作的?当您使用箭头函数和类属性插件时,它会转换为类似下面的内容,在您使用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 () {};
}
Run Code Online (Sandbox Code Playgroud)
  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 () {}
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用createClassreact,它为你做绑定.注意我们只对其类属性绑定魔法使用react.我们不是在创建反应组件.

    import React from 'react'
    
    const OAuth = React.createClass({
      register (server, err, next) {
        this.server = server
        this.registerRoutes()
      }
    
      registerRoutes () {}
    })
    
    Run Code Online (Sandbox Code Playgroud)
  3. 只有使用autoBind反应级.这里我们使用ES6 +类语法制作一个react组件来使用该autoBind方法.我们没有用componentWillMount,render等,其提供有反应的组分.

    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 () {}
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 滚动您自己的类属性绑定器.这是一个很好的练习,与选项2基本相同,也可能是更少的代码.

    // 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);
      })
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 如果您确实想要创建反应组件,可以将箭头函数和属性初始值设定项组合起来

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

  • 你的第二种方法很完美. (2认同)