为什么我的 ES6(使用 Babel)class 说 `this` 在实例方法中未定义?
Why does my ES6 (using Babel) class say `this` is undefined in an instance method?
我正在使用 Hapi.JS 在 Node 中构建应用程序。
我有一个 class 的身份验证插件,它给我带来了各种各样的问题。当我尝试从 class 的方法中引用 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 class with babel 不会为你自动绑定 this
。自引入 class
以来,这是一个常见的误解。有多种方法可以解决。
使用 ES7。 Babel 有一个实验性的(截至此 post)class-properties 插件。
class OAuth {
constructor () {}
register = (server, err, next) => {
this.server = server
this.registerRoutes()
}
registerRoutes = () => {}
}
这是如何工作的?当您将 arrow-functions 与 class-properties 插件一起使用时,它会转换为类似以下内容,并按照您使用 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 属性
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 属性 绑定魔法。我们不是在创建 React 组件。
import React from 'react'
const OAuth = React.createClass({
register (server, err, next) {
this.server = server
this.registerRoutes()
}
registerRoutes () {}
})
仅使用 react-class 中的 autoBind
。这里我们使用 ES6+ class 语法制作一个 React 组件,只是为了使用 autoBind
方法。我们不必使用 componentWillMount
、render
等,这些都是 React 组件提供的
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 () {}
}
自己制作 class 属性 活页夹。这是一个很好的练习,与选项 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);
})
}
如果你真的想创建 React 组件,你可以结合 arrow-functions 和 属性 初始化器来做类似
class OAuthComponent extends React.Component {
whateverMethodYouWant = (event) => {
this.setState({somePropertyYouCareAbout: true}) // this is bound
}
anotherMethod = () => {
this.whateverMethodYouWant() // this is bound
}
}
我正在使用 Hapi.JS 在 Node 中构建应用程序。
我有一个 class 的身份验证插件,它给我带来了各种各样的问题。当我尝试从 class 的方法中引用 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 class with babel 不会为你自动绑定 this
。自引入 class
以来,这是一个常见的误解。有多种方法可以解决。
使用 ES7。 Babel 有一个实验性的(截至此 post)class-properties 插件。
class OAuth { constructor () {} register = (server, err, next) => { this.server = server this.registerRoutes() } registerRoutes = () => {} }
这是如何工作的?当您将 arrow-functions 与 class-properties 插件一起使用时,它会转换为类似以下内容,并按照您使用 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 属性
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 属性 绑定魔法。我们不是在创建 React 组件。import React from 'react' const OAuth = React.createClass({ register (server, err, next) { this.server = server this.registerRoutes() } registerRoutes () {} })
仅使用 react-class 中的
autoBind
。这里我们使用 ES6+ class 语法制作一个 React 组件,只是为了使用autoBind
方法。我们不必使用componentWillMount
、render
等,这些都是 React 组件提供的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 () {} }
自己制作 class 属性 活页夹。这是一个很好的练习,与选项 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); }) }
如果你真的想创建 React 组件,你可以结合 arrow-functions 和 属性 初始化器来做类似
class OAuthComponent extends React.Component { whateverMethodYouWant = (event) => { this.setState({somePropertyYouCareAbout: true}) // this is bound } anotherMethod = () => { this.whateverMethodYouWant() // this is bound } }