Javascript ES6中嵌套类的上下文很奇怪

Javascript ES6中嵌套类的上下文很奇怪,javascript,reactjs,firefox,webpack,Javascript,Reactjs,Firefox,Webpack,我有以下嵌套类结构: import React, {Component} from 'react'; import {TextField} from '@material-ui/core'; import './ProfileEditor.css'; export default class ProfileEditor extends Component { SyncedTextField = class SyncedTextField extends Component {

我有以下嵌套类结构:

import React, {Component} from 'react';
import {TextField} from '@material-ui/core';
import './ProfileEditor.css';

export default class ProfileEditor extends Component {
    SyncedTextField = class SyncedTextField extends Component {
        onChange = event => {
            console.log(this);
        };

        render() {
            return (
                <TextField
                    {...this.props}
                    onChange={this.onChange}/>
            );
        }
    };

    render() {
        return (
            <form className={"ProfileEditor"}>
                <this.SyncedTextField/>
            </form>
        );
    }
}
import React,{Component}来自'React';
从“@material ui/core”导入{TextField};
导入“/ProfileEditor.css”;
导出默认类ProfileEditor扩展组件{
SyncedTextField=类SyncedTextField扩展组件{
onChange=事件=>{
console.log(this);
};
render(){
返回(
);
}
};
render(){
返回(
);
}
}
当代码被Webpack绑定并在Firefox中运行时,它会正确地运行
this.onChange
,但输出的
this
引用了
ProfileEditor
类的上下文

这太奇怪了,因为在JSX中,当我引用“This”时,它正确地指向SyncedTextField,但在onChange方法中,它指向
ProfileEditor

我确实在
ProfileEditor
中添加了一些属性来检查我自己的健康状况,这些属性显示为
ProfileEditor
中声明的属性,即使在SyncedTextField中提供了冲突的定义


有人能告诉我如何避免这个问题吗?是什么导致了这个问题?

浏览器开发工具可能会出现不正确的行为。但在这种情况下,这是由transpiler的工作方式引起的。Babel 6类字段(第3阶段建议)转换实现中存在错误

onChange
中,使用Babel输出
ProfileEditor
作为
this
进行编译

下面是来自Babel输出的
SyncedTextField
构造函数:

function SyncedTextField() {
  var _ref2;

  var _temp2, _this2, _ret2;

  _classCallCheck(this, SyncedTextField);

  for (
    var _len2 = arguments.length, args = Array(_len2), _key2 = 0;
    _key2 < _len2;
    _key2++
  ) {
    args[_key2] = arguments[_key2];
  }

  return (
    (_ret2 = ((_temp2 = ((_this2 = _possibleConstructorReturn(
      this,
      (_ref2 =
        SyncedTextField.__proto__ ||
        Object.getPrototypeOf(SyncedTextField)).call.apply(
        _ref2,
        [this].concat(args)
      )
    )),
    _this2)),
    (_this2.onChange = function(event) {
      console.log(_this); // SHOULD BE _this2
    }),
    _temp2)),
    _possibleConstructorReturn(_this2, _ret2)
  );
}
当输入时,它输出
SyncedTextField

使用TypeScript编译(默认情况下由Stackblitz在React模板中使用)按预期工作,并在
onChange
中将
SyncedTextField
输出为
this

由于类很少以这种方式定义,巴别塔bug通常不适用。

SyncedTextField=class-SyncedTextField扩展组件{…}
是反模式。没有理由这样嵌套类表达式。它的效率很低,因为它是在每个
ProfileEditor
实例化上进行计算的。它应该是类声明,这样可以用作

即使出于可测试性或可扩展性的原因,
SyncedTextField
应定义为
ProfileEditor
组件的属性,最好将其设为prototype属性:

class SyncedTextField extends Component {...}

class ProfileEditor extends Component {
  get SyncedTextField() { return SyncedTextField }
  ...
}

不正确的行为可能特定于浏览器开发工具。但在这种情况下,这是由transpiler的工作方式引起的。Babel 6类字段(第3阶段建议)转换实现中存在错误

onChange
中,使用Babel输出
ProfileEditor
作为
this
进行编译

下面是来自Babel输出的
SyncedTextField
构造函数:

function SyncedTextField() {
  var _ref2;

  var _temp2, _this2, _ret2;

  _classCallCheck(this, SyncedTextField);

  for (
    var _len2 = arguments.length, args = Array(_len2), _key2 = 0;
    _key2 < _len2;
    _key2++
  ) {
    args[_key2] = arguments[_key2];
  }

  return (
    (_ret2 = ((_temp2 = ((_this2 = _possibleConstructorReturn(
      this,
      (_ref2 =
        SyncedTextField.__proto__ ||
        Object.getPrototypeOf(SyncedTextField)).call.apply(
        _ref2,
        [this].concat(args)
      )
    )),
    _this2)),
    (_this2.onChange = function(event) {
      console.log(_this); // SHOULD BE _this2
    }),
    _temp2)),
    _possibleConstructorReturn(_this2, _ret2)
  );
}
当输入时,它输出
SyncedTextField

使用TypeScript编译(默认情况下由Stackblitz在React模板中使用)按预期工作,并在
onChange
中将
SyncedTextField
输出为
this

由于类很少以这种方式定义,巴别塔bug通常不适用。

SyncedTextField=class-SyncedTextField扩展组件{…}
是反模式。没有理由这样嵌套类表达式。它的效率很低,因为它是在每个
ProfileEditor
实例化上进行计算的。它应该是类声明,这样可以用作

即使出于可测试性或可扩展性的原因,
SyncedTextField
应定义为
ProfileEditor
组件的属性,最好将其设为prototype属性:

class SyncedTextField extends Component {...}

class ProfileEditor extends Component {
  get SyncedTextField() { return SyncedTextField }
  ...
}

在Microsoft Edge中测试时也会发生同样的情况。是的,没错,因为它是一个箭头函数。。。其
与函数是常规表示法(即您如何
呈现()
)不同哦,因此箭头函数将保持绑定到
ProfileEditor
范围,而不是
SyncedTextField
?我觉得有点奇怪,但是谢谢!这与定义函数时这个是什么有关,或者其他什么-我在解释箭头函数时很糟糕:p有什么原因不能
一次更改(事件)吗{
…等等?不,没有,我只是在试验上下文是什么,结果真的让我吃惊。我想这可能是因为
在内部是一种提供带有原型的函数的更奇特的方式,我在登录时看到了这一点。在Microsoft Edge中测试时也会发生同样的事情。是的,这是正确的,因为这是一个arrow函数…它的
与函数是常规符号时的情况不同(即,您是如何
呈现()的
)哦,所以箭头函数将保持绑定到
ProfileEditor
范围,而不是
SyncedTextField
?对我来说似乎有点奇怪,但是谢谢!这与定义函数时
这个
是什么有关-我很难解释箭头函数:p有什么原因不能
一次更改吗(活动){
…等等?不,没有,我只是在试验上下文是什么,结果真的让我吃惊。我想这可能是因为
在内部是一种更为奇特的方式来提供一个带有原型的函数,我在登录时看到了这一点。答案令人惊讶。Create React应用程序会自动添加Babel吗?作为旁注,我不想提取SyncedTextField,因为它管理了
ProfileEditor
的状态。create-react-app只是用于设置Webpack+Babel模板的CLI工具。因此,是的,它使用了Babel。我希望这个问题在Babel 7中得到修复,这样你就可以弹出项目并将Babel升级到7。因为它管理了Profil