调用 ES6 方法时绑定上下文。如何从称为回调的方法中访问对象?

新手上路,请多包涵

我正在努力思考 ES6 中类的语法。同时通过 Bonnie Eisenman 的 Learning React Native 学习 Fabric native。

我遇到了一个关于在回调中访问 this 的问题,当回调是一个类“方法”时。我知道有关词法的问题 this 在回调中已在 StackOverflow 上多次提出。例如在 How to access the correct `this` context inside a callback? .

根据我的在线研究,我找到了一个解决方案。但我不确定这是在 ES6 中执行此操作的正确方法。

当我尝试以下操作时出现了我的问题:

 class WeatherProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
      zip: ''
    };
  }

  _handleTextChange(event) {
    console.log(event.nativeEvent.text);
    this.setState({zip: event.nativeEvent.text})
  }

  render() {
    return (
      <TextInput
        style={styles.input}
        onSubmitEditing={this._handleTextChange}/>
    );
  }
}

(我只是对书中的示例稍作修改,以匹配 ES6 类语法和导入/导出语法,而不是 Require。)

如果我这样做, this_handleTextChange 未定义(无法读取未定义的属性“setState”)。我对此感到惊讶。来自其他 OO 语言,我解释好像这个方法的行为更像是一个静态方法。

我已经能够通过跳过类方法并使用箭头符号来解决这个问题。 onSubmitEditing={event => this.setState({name: event.nativeEvent.text})} 。哪个工作正常。我对此没有任何问题或困惑。

不过,我真的很想弄清楚如何调用类方法。经过大量研究后,我设法通过执行以下操作使其工作: onSubmitEditing={this._handleTextChange.bind(this)} 。也许我误解了 JavaScript 的一个基本方面(我是 JS 的初学者),但这对我来说似乎完全是疯了。如果不显式地将对象绑定回……它是自己的方法,在它被调用的地方,真的没有办法从方法内部访问对象的上下文吗?

我还尝试在构造函数中添加 var self = this; 并在 self.setState _handleTextChange 。但是发现这行不通并不太惊讶。

当对象作为回调调用时,从其方法之一访问对象的正确方法是什么?

原文由 rod 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 251
2 个回答

React.createClass (ES5) 创建类的方式有一个内置功能,可以自动将所有方法绑定到 this 。但是在 ES6 中引入 classes 并迁移 React.createClass 时,他们发现对于不习惯其他类中的此功能的 JavaScript 开发人员来说可能会有点困惑,或者当他们从 React 迁移时可能会感到困惑到其他班级。

因此,他们决定不将此内置到 React 的类模型中。如果需要,您仍然可以在构造函数中显式预绑定方法

class WeatherProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
      zip: ''
    };
    this._handleTextChange = this._handleTextChange.bind(this); //Binding to `this`
  }

  _handleTextChange(event) {
    console.log(event.nativeEvent.text);
    this.setState({zip: event.nativeEvent.text})
  }

但是我们总是有一个简单的方法来避免这种预绑定。是的!你说对了。箭头函数。

 class WeatherProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
      zip: ''
    };
  }

  _handleTextChange = event => {
    console.log(event.nativeEvent.text);
    this.setState({zip: event.nativeEvent.text})
  }

  render() {
    return (
      <TextInput
        style={styles.input}
        onSubmitEditing={this._handleTextChange}/>
    );
  }
}

顺便说一句,这都是关于 React 的。 ES6 类总是有一种方法可以从方法内部访问对象的上下文,而无需将对象显式绑定回它自己的方法。

 class bindTesting {
  constructor() {
    this.demo = 'Check 1';
  }

  someMethod() {
    console.log(this.demo);
  }

  callMe() {
    this.someMethod();
  }
}

let x = new bindTesting();
x.callMe(); //Prints 'Check 1';

但是如果我们在 JSX 表达式中调用它,这不会打印 ‘Check 1’。

编辑 :: 正如@Oka 所提到的,类主体中的箭头函数是 ES7+ 功能,并且在 Compiler/polyfills 中可用,例如 babel。如果您不使用支持此功能的转译器,我们可以像上面提到的那样绑定到 this 或像这样编写一个新的 BaseComponent(这是个坏主意)

 class BaseComponent extends React.Component {
 _bind(...methods) {
  methods.forEach( (method) => this[method] = this[method].bind(this) );
 }
}

class ExampleComponent extends BaseComponent {
 constructor() {
  super();
  this._bind('_handleTextChange', '_handleClick');
 }
 // ...
}

原文由 Prasanth 发布,翻译遵循 CC BY-SA 3.0 许可协议

暂时脱离 ES6 和 React,在常规的旧 JavaScript 中,当你传递一个对象的方法时,它只是对函数本身的引用,而不是对象 函数。

任何调用函数都可以选择使用隐式 this ,通过正常调用函数,或者它甚至可以选择使用 .call.apply ,733 更改上下文 .bind

 var O = {
  foo: function () {
    console.log(this);
  },
  bar: 51
};

O.foo(); // `this` is O, the implicit context, inferred from the object host

var foo = O.foo;

foo(); // `this` is is the global object, or undefined in Strict Mode

发生的事情是,您正在将 _handleTextChange 函数 传递给事件发射器,该发射器稍后会执行。事件发射器不知道它收到了作为 方法 的函数。它只是执行它。

 var O = {
  foo: function (event) {
    console.log(this);
    console.log(event);
  },
  bar: 51
};

function invoke (func) { // the function reference held by O.foo is now held by `func`
  func('some param'); // it has no idea as to what the contextual `this` is bound to, maybe its implicitly global, maybe its explicitly bound, maybe its undefined
}

invoke(O.foo);

invoke(O.foo.bind(O)); // A copy of the function with the context explicitly bound

看一下上下文共享:

 function foo () {
  console.log(this.a);
}

// Both object hold references to the foo function
var O = { foo : foo, a : 5 },
    O2 = { bar : foo, a : 1 };

O.foo(); // implicit `this` from O
O2.bar(); // implicit `this` from O2

var Z = { a : 23 };

O.foo.call(Z); // explicit `this` from Z

这些例子会让你变得任意复杂。

原文由 Oka 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题