ES6函数,箭头函数和ES6类中的“this” [英] ES6 functions, arrow functions and 'this' in an ES6 class

查看:181
本文介绍了ES6函数,箭头函数和ES6类中的“this”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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类方法但将其更改为箭头函数则修复它。

What is the difference between the two type of functions declared in the class (onChange and onSubmit). I get an error on referencing this.sate in const url if I declare it as an ES6 class method but changing it to arrow function fixes it.

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

另外,我该怎么做呢?比方说,如果我想使用相同的onSubmit函数(ES6类方法),但是当我调用它时(在表单元素中)想要处理它,我该怎么办?

Also, how do I do it the other way? Say, if I want to use the same onSubmit function (ES6 class method) but want to handle this when I call it (in the form element), how do I do it ?

使用this.onSubmit.bind(this)

推荐答案

知道这一点非常重要语法:

It's important to know that this syntax:

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

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

is just syntactic sugar for creating an instance method in the class constructor:

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

注意:此语法不是官方部分尚未使用JavaScript语言(目前处于第3阶段),因此您必须使用像Babel一样处理它

Note: This syntax is not an official part of the JavaScript language yet (currently in stage 3) so you must use a transpiler like Babel to handle it.

方法的值c>是类 A ,因为这是这个指向构造函数的内容(因为 arrow functions 从它们定义的范围继承上下文:

The value of this within method is the class A because that is what this points to in the constructor (since arrow functions inherit the context from the scope they are defined in):

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

const instance = new A();
console.log(instance.method() === instance); // true

定义常规(非箭头函数)方法在类上创建一个类原型(不是实例)的方法,但没有规定这个将是什么(因为这个在JS中是动态的,取决于函数如何调用,而不是如何定义

Defining a regular (non-arrow function) method on the class creates a method on the class prototype (not instance) but sets no rules on what this will be (since this is dynamic in JS and depends on how a function is called, not how it's defined).

class A {
  method() {}
}

console.log(new A().method === A.prototype.method); // true

如果调用以这两种方式定义的方法在类实例上(通过),根据的规则,在调用函数时绑定此作为一个对象的方法,这个将指向两种情况下的类实例:

If methods defined in either of these ways are called on the class instance (via the .), as per the rule of how this is bound when a function is called as a method of an object, this will point to the class instance in both cases:

class A {
  constructor() {
    this.methodOnInstance = () => this;
  }
  methodOnPrototype() { return this; }
}

const instance = new A();
console.log(
  instance.methodOnInstance() === instance.methodOnPrototype(), // true
  instance.methodOnPrototype() === instance // true
);

上面两个方法声明的一个主要区别是实例方法有这个 总是固定在类实例上,而类(原型)方法没有(我们可以通过使用 Function.prototype.apply Function.prototype.call

One major difference between the two method declarations above is that the instance method has this always fixed to the class instance while the class (prototype) method does not (we can change it by using Function.prototype.apply or 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
);

<$ c $的常见情况c>此更改位于事件处理程序中,其中事件处理程序调用传递给它的函数,并将上下文绑定到发生事件的元素(因此会覆盖这个是被点击的元素或事件是什么)

A common occurrence where the this changes is within an event handler, where the event handler calls the function passed into it and binds the context to the element on which the event happened (so overrides the value of this to be the element that was clicked or whatever the event was)

这在React中也适用于所有人(合成)DOM事件处理程序。

This happens in React as well for all (synthetic) DOM event handlers.

因此,如果我们希望我们方法的上下文始终指向React组件的实例,我们可以使用实例方法。

Therefore, if we want our method's context to always point to the instance of the React component, we can use the instance method.

另一种限制上下文但不使用特殊实例的方法需要Babel的方法语法是direc通过使用绑定上下文从类(原型)方法创建一个新函数来自己创建一个实例方法(使用 Function.prototype.bind ):

Another way of restricting the context but not using the special instance method syntax that requires Babel is to directly create an instance method ourselves by creating a new function from the class (prototype) method with a bound context (using 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及以下)。

This allows us get arrive to the same result as using the special instance method syntax but with the currently available tools (ES2017 and under).

如果由于某种原因我们想要一个总是绑定到不是该类实例的方法的方法,我们可以这样做:

If for some reason we want a method that is always bound to something that is not an instance of the class, we can do that as well:

class A {
  constructor() {
    this.method = this.method.bind(console);
  }
  method() { return this; }
}

const instance = new A();
console.log(
  instance.method() === console // true
);

这篇关于ES6函数,箭头函数和ES6类中的“this”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆