为什么我的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
以来,这是一个常见的误解。 有多种方法来解决它。
-
使用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 () {}; }
-
在构造函数中绑定您的类属性
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 () {} }
-
从反应中使用
createClass
,它为你做绑定。 请注意,我们只对其类属性绑定魔法使用反应。 我们不是创build反应组件。import React from 'react' const OAuth = React.createClass({ register (server, err, next) { this.server = server this.registerRoutes() } registerRoutes () {} })
-
只使用反应级别的
autoBind
。 在这里,我们使用ES6 +类语法来创build反应组件,只是使用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 () {} }
-
滚动你自己的类属性联编程序。 这是一个很好的练习,基本上和选项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); }) }
-
如果你真的想创build反应组件,你可以组合箭头函数和属性初始值设定项来做类似的事情
class OAuthComponent extends React.Component { whateverMethodYouWant = (event) => { this.setState({somePropertyYouCareAbout: true}) // this is bound } anotherMethod = () => { this.whateverMethodYouWant() // this is bound } }