class App extends Component { constructor(props) { … }
onChange = (e) => this.setState({term: e.target.value}) onSubmit(e){ e.preventDefault(); const api_key = "C1hha1quJAQZf2JUlK"; const url = `http://api.giphy.com/v1/gifs/search?q=${this.state.term}&api_key=${api_key}`; } render() { return ( <div> <form onSubmit={this.onSubmit}> <input value={this.state.term} onChange={this.onChange}/> <button>Search!</button> </form> </div> ); } }
在类中声明的两种函数 (onChange和onSubmit) 之间有什么区别?如果我将其声明为ES6类方法,但在 const url中 引用this.sate时出现错误,但是将其更改为arrow函数可以解决此问题。
我想知道两种情况下如何正确处理“ this”
另外,我该如何做呢?说,如果我想使用相同的onSubmit函数(ES6类方法),但是想在调用它(在form元素中)时进行处理,该怎么办?
使用this.onSubmit.bind(this) 吗?
重要的是要知道以下语法:
class A { method = () => {} }
只是在类构造函数中创建实例方法的语法糖:
class A { constructor() { this.method = () => {} } }
注意:该语法尚未成为JavaScript语言的正式组成部分(当前处于第3阶段),因此您必须使用Babel这样的编译器来处理它。
值this内method是一流的A,因为这是this在构造函数中指向(因为箭头的功能继承了它们在规定的范围内的情况下):
this
method
A
class A { constructor() { this.method = () => this; } } const instance = new A(); console.log(instance.method() === instance); // true
在类上定义常规(非箭头函数)方法会在类原型(而不是实例)上创建方法,但不会设置任何规则this(因为this在JS中是动态的,并且取决于函数的调用方式,而不是函数的调用方式)定义)。
class A { method() {} } console.log(new A().method === A.prototype.method); // true
如果按照上述两种方法之一定义的方法(通过.)在类实例上被调用,则按照将this函数作为对象的方法调用时绑定方式的规则,this在两种情况下都将指向类实例:
.
class A { constructor() { this.methodOnInstance = () => this; } methodOnPrototype() { return this; } } const instance = new A(); console.log( instance.methodOnInstance() === instance.methodOnPrototype(), // true instance.methodOnPrototype() === instance // true );
上面两个方法声明之间的主要区别在于,实例方法this 始终 固定在类实例上,而类(原型)方法没有固定(我们可以使用Function.prototype.apply或Function.prototype.call对其进行更改)
class A { constructor() { this.methodOnInstance = () => this; } methodOnPrototype() { return this; } } const instance = new A(); console.log( instance.methodOnInstance() === instance.methodOnPrototype(), // true instance.methodOnPrototype.call('new this') === 'new this' // true );
this更改发生在事件处理程序中的常见情况,其中事件处理程序调用传递给它的函数,并将上下文绑定到发生事件的元素(因此,将的值覆盖为this被单击的元素或活动原为
对于所有(合成)DOM事件处理程序,这也会在React中发生。
因此,如果我们希望方法的上下文始终指向React组件的实例,则可以使用instance方法。
限制上下文但不使用需要Babel的特殊实例方法语法的另一种方法是,通过在具有绑定上下文的类(原型)方法中创建一个新函数(使用Function.prototype.bind)来直接直接创建实例方法:
class A { constructor() { this.methodOnInstance = this.methodOnPrototype.bind(this); } methodOnPrototype() { return this; } } const instance = new A(); console.log( instance.methodOnInstance() === instance.methodOnPrototype(), // true instance.methodOnPrototype() === instance // true );
这使我们可以获得与使用特殊实例方法语法相同的结果,但使用当前可用的工具(ES2017及以下)。
如果由于某种原因我们想要一个始终绑定到不是该类实例的东西的方法,我们也可以这样做:
class A { constructor() { this.method = this.method.bind(console); } method() { return this; } } const instance = new A(); console.log( instance.method() === console // true );