为什么我的ES6(使用Babel)类说"this"在实例方法中未定义? [英] Why does my ES6 (using Babel) class say `this` is undefined in an instance method?

查看:149
本文介绍了为什么我的ES6(使用Babel)类说"this"在实例方法中未定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am building an application in Node using Hapi.JS.

我有一个用于身份验证插件的类,它给我带来各种各样的问题.当我尝试从类的方法中引用this时,出现一条错误消息,提示未定义this.为什么会这样?

I have a class for an authentication plugin that is giving me all sorts of problems. When I attempt to reference this from within a method on the class, I get an error saying that this is undefined. Why is this happening?

摘录:

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);

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

Every time the register function is called, I receive this error:

TypeError: Cannot set property 'server' of undefined

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

Why on earth is my instance not working?

推荐答案

带有babel的ES6类不会为您自动绑定this.自引入class以来,这是一个常见的误解.有多种解决方法.

ES6 class with babel doesn't autobind this for you. This is a common misconception since class was introduced. There are multiple ways to solve it.

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

class OAuth {
  constructor () {}

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

  registerRoutes = () => {}
}  

这是如何工作的?当您将箭头功能与class-properties插件一起使用时,它会转换为如下所示的内容,并在您使用class语法时按预期进行绑定.

How does this work? When you use arrow-functions along with the class-properties plugin, it gets transformed to something like the following, binding this as you expect when you use class syntax.

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. 在构造函数中绑定类属性

  1. Bind your class properties in the constructor

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 () {}
}

  • 使用react中的createClass,它会为您进行绑定.注意,我们仅将react用于其class属性绑定魔术.我们不创建反应组件.

  • Use createClass from react, which does the binding for you. Note we're only using react for its class property binding magic. We are not creating react components.

    import React from 'react'
    
    const OAuth = React.createClass({
      register (server, err, next) {
        this.server = server
        this.registerRoutes()
      }
    
      registerRoutes () {}
    })
    

  • 仅使用反应类中的autoBind.在这里,我们使用ES6 +类语法来制作React组件,只是为了使用autoBind方法.我们不必使用带有响应组件的componentWillMountrender等.

  • Use only autoBind from react-class. Here we're making a react component using ES6+ class syntax just to use the autoBind method. We don't have to use componentWillMount, render, etc, which are provided with react components.

    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 () {}
    }
    

  • 滚动您自己的类属性绑定器.这是一个很好的练习,与选项2基本相同,可能也减少了代码.

  • Roll your own class property binder. It's a nice exercise, basically the same as option 2, possibly less code as well.

    // 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);
      })
    }
    

  • 如果您确实想创建react组件,则可以结合使用箭头功能和属性初始化程序来做类似的事情

  • If you actually want to create react components, you can combine arrow-functions and property initializers to do something like

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

  • 这篇关于为什么我的ES6(使用Babel)类说"this"在实例方法中未定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆