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)中声明的两种函数之间有什么区别。我在 const url 中引用this.sate时出错,如果我将其声明为ES6类方法但将其更改为箭头函数则会修复它。
我想知道这个&#39;这个&#39;在两种情况下处理
另外,我该怎么做呢?比方说,如果我想使用相同的onSubmit函数(ES6类方法),但是当我调用它时(在表单元素中)想要处理它,我该怎么办?
使用this.onSubmit.bind(this)?
答案 0 :(得分:8)
了解这种语法非常重要:
class A {
method = () => {}
}
只是用于在类构造函数中创建实例方法的语法糖:
class A {
constructor() {
this.method = () => {}
}
}
注意:此语法尚未成为JavaScript语言的官方部分(currently in stage 3),因此您必须使用transpiler like Babel to handle it。
this
中method
的值是类A
,因为这是this
在构造函数中指向的内容(因为arrow functions继承了上下文它们的定义范围):
class A {
constructor() {
this.method = () => this;
}
}
const instance = new A();
console.log(instance.method() === instance); // true
&#13;
在类上定义常规(非箭头函数)方法会在类原型(而非实例)上创建一个方法,但不会对this
将成为什么规则(因为this
是动态的JS和depends on how a function is called, not how it's defined)。
class A {
method() {}
}
console.log(new A().method === A.prototype.method); // true
&#13;
如果在类实例上调用以这两种方式定义的方法(通过.
),则根据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
);
&#13;
上面两个方法声明之间的一个主要区别是实例方法将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
);
&#13;
this
更改的常见情况是在事件处理程序中,事件处理程序调用传递给它的函数,并将上下文绑定到发生事件的元素(因此会覆盖{{{ 1}}是被点击的元素或事件是什么)
这在React中也适用于所有(synthetic)DOM事件处理程序。
因此,如果我们希望方法的上下文始终指向React组件的实例,我们可以使用实例方法。
限制上下文但不使用需要Babel的特殊实例方法语法的另一种方法是通过使用绑定上下文从类(prototype)方法创建新函数来直接创建实例方法(使用{{3} }):
this
&#13;
这使得我们可以获得与使用特殊实例方法语法相同的结果,但使用当前可用的工具(ES2017及以下)。
如果由于某种原因我们想要一个总是绑定到不是该类实例的方法的方法,我们也可以这样做:
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
);
&#13;
答案 1 :(得分:1)
箭头函数表达式的语法短于函数 表达式并没有自己的this,arguments,super或者 new.target。这些函数表达式最适合非方法 函数,它们不能用作构造函数。
箭头函数在词法上绑定它们的上下文,因此这实际上是指原始上下文。
在ES3 / 4函数声明中,您可以通过存储其他变量来使用this
。
const that = this;
onSubmit(e){
e.preventDefault();
const api_key = "***************";
const url = `http://api.giphy.com/v1/gifs/search?q=${that.state.term}&api_key=${api_key}`;
}
答案 2 :(得分:0)
另外,我该怎么做呢?比方说,如果我想使用相同的onSubmit函数(ES6类方法),但是当我调用它时(在表单元素中)想要处理它,我该怎么办?
使用this.onSubmit.bind(this)?
是的,您必须将方法绑定到构造函数中的组件。这是因为箭头函数会自动绑定到类中,因此在此方法中设置了此范围。虽然onSubmit
是一个尚未绑定的常规函数,因此方法内部将引用该函数而不是组件。
答案 3 :(得分:0)
您需要在类的构造函数中使用bind
和ES6类方法。从本质上讲,箭头功能会自动为您执行此操作。
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
这里要注意的更重要的是我相信这里的箭头函数将在类的每个实例上创建,其中ES6类方法将成为类的原型的一部分并在所有实例之间共享。
答案 4 :(得分:0)
关键区别在于,在ES5中我们没有自动绑定,这意味着您必须手动绑定事件处理函数,以便在函数内部使用状态或道具进行反应。但在ES6中它会自动绑定。这是关键的区别
ES5:你最好在构造函数
中绑定onSubmit//is valid
this.onSubmit = this.onSubmit.bind(this);
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}`;
}
ES6:
以下内容有效,因为它会自动绑定。
onChange = (e) => this.setState({term: e.target.value})