ES6 类中的 ES6 函数、箭头函数和“this”

IT技术 javascript reactjs ecmascript-6 es6-class arrow-functions
2021-03-22 19:47:31
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)有什么区别如果我将this.sate声明为 ES6 类方法但将其更改为箭头函数可以修复它,则const url 中引用 this.sate 时会出现错误

我想知道在这两种情况下如何处理“这个”

另外,我如何以另一种方式做到这一点?比如说,如果我想使用相同的 onSubmit 函数(ES6 类方法)但想在调用它时(在表单元素中)处理它,我该怎么做?

使用 this.onSubmit.bind(this)

5个回答

重要的是要知道这个语法:

class A {
  method = () => {}
}

只是在类构造函数中创建实例方法的语法糖:

class A {
  constructor() {
    this.method = () => {}
  }
}

注意:此语法还不是 JavaScript 语言的正式部分(目前处于第 3 阶段),因此您必须使用像 Babel这样的转译器来处理它

thismethod是一流的A,因为这是this在构造函数中指向(因为箭头的功能继承了它们在规定的范围内的情况下):

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.applyFunction.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 组件的实例,我们可以使用实例方法。

另一种限制上下文但不使用需要 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
);

箭头函数表达式的语法比函数表达式短,并且没有自己的 this、arguments、super 或 new.target。这些函数表达式最适合非方法函数,它们不能用作构造函数。

箭头函数在词汇上绑定了它们的上下文,因此 this 实际上是指原始上下文。

在 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}`;
  }

另外,我如何以另一种方式做到这一点?比如说,如果我想使用相同的 onSubmit 函数(ES6 类方法)但想在调用它时(在表单元素中)处理它,我该怎么做?

使用 this.onSubmit.bind(this) ?

是的,您必须将该方法绑定到构造函数中的组件。这是因为箭头函数会自动绑定到类,因此 this 的范围是在方法中设置的。虽然onSubmit是一个尚未绑定的常规函数​​,因此方法内部的 this 将引用函数而不是组件。

您需要bind在类的构造函数中使用 ES6 类方法。本质上,箭头函数会自动为你做这件事。

constructor(props) {
  super(props);

  this.onSubmit = this.onSubmit.bind(this);
}

这里需要注意的更重要的一点是,我相信这里的箭头函数将在类的每个实例上创建,其中 ES6 类方法将成为类原型的一部分并在所有实例之间共享。

关键区别在于,在 ES5 中,我们没有自动绑定,这意味着您必须手动绑定事件处理函数,以便在 react 中使用函数内的 state 或 props。但是在 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})
不,它不进行自动绑定。它只是没有将函数放在原型上。
2021-04-23 19:47:31
对。我理解使用术语自动绑定:)
2021-04-29 19:47:31
绑定意味着bind在通用(动态this)方法上使用。
2021-05-10 19:47:31