简体   繁体   English

是否可以在 ES6 的类中使用箭头函数?

[英]Is it possible to use arrow functions in classes with ES6?

My question is very simple.我的问题很简单。 If I have a class in ES6 is it possible to use an arrow function within it?如果我在 ES6 中有一个类,是否可以在其中使用箭头函数?

import React, { Component } from 'react';

export default class SearchForm extends Component {

  state = {
    searchText: ''
  }

  onSearchChange = e => {
    this.setState({ searchText: e.target.value });
  }

  handleSubmit = e => {
    e.preventDefault();
    this.props.onSearch(this.query.value);
    e.currentTarget.reset();
  }

  render() {
    return (
      <form className="search-form" onSubmit={this.handleSubmit} >
        <label className="is-hidden" htmlFor="search">Search</label>
        <input type="search"
               onChange={this.onSearchChange}
               name="search"
               ref={(input) => this.query = input}
               placeholder="Search..." />
        <button type="submit" id="submit" className="search-button">
          <i className="material-icons icn-search">search</i>
        </button>
      </form>
    );
  }
}

The reason I ask is that I get an error in my console, even when using Babel.我问的原因是我的控制台出现错误,即使在使用 Babel 时也是如此。 It seems like there's a lot of resources on the internet stating you can do this (most of which are about developing with React).互联网上似乎有很多资源表明您可以做到这一点(其中大部分是关于使用 React 进行开发的)。

Is this something that Babel should do, and will eventually become natively supported?这是 Babel 应该做的事情,并且最终会得到本地支持吗?

The error I get is an unexpected = sign, just before the parens.我得到的错误是一个意外的 = 符号,就在括号之前。

EDIT: I forgot to mention, the reason I wish to do this is to make use of the this keyword in context of the class.编辑:我忘了提到,我希望这样做的原因是在类的上下文中使用this关键字。 If I use a regular function - to my understanding - I would have to bind this to the function.如果我使用一个普通的功能-我的理解-我将不得不结合this给函数。 I'm trying to look for a nicer way of doing that.我正在寻找一种更好的方法来做到这一点。

In order to do that, you'll need to add the transform-class-properties babel plugin, which allows you to have auto-bound class methods like you are attempting.为了做到这一点,您需要添加transform-class-properties babel 插件,它允许您像尝试一样拥有自动绑定的类方法。

Unlike what others have just suggested, there IS value in doing this.与其他人刚刚建议的不同,这样做是有价值的。 Namely, your class function automatically has the class this bound to it, without having to manually bind it in your constructor.也就是说,您的类函数会自动将类this绑定到它,而无需在构造函数中手动绑定它。

Without the transform-class-properties plugin, you could do:如果没有transform-class-properties插件,你可以这样做:

export default class SearchForm extends Component {

  constructor(props) {
    super(props)
    this.doSomething = this.doSomething.bind(this)
  }

  doSomething () {
    console.log(this) // <-- 'this' is the class instance
  }
}

With the plugin:使用插件:

export default class SearchForm extends Component {

  doSomething = () => {
    console.log(this) // <-- 'this' is the class instance, no binding necessary
  }
}

Heres and article that explains it (among other thing) fairly well and consisely: https://medium.com/@joshblack/writing-a-react-component-in-es2015-a0b27e1ed50a这里和解释它的文章(除其他外)相当好和简洁: https ://medium.com/@joshblack/writing-a-react-component-in-es2015-a0b27e1ed50a

Yes it is possible to use arrow functions inside ES6 classes.是的,可以在 ES6 类中使用箭头函数。 I noticed that you are not calling super inside your constructor you have to do that if you are extending and overriding the constructor.我注意到您没有在构造函数中调用super ,如果您要扩展和覆盖构造函数,则必须这样做。

Other than that your code compiles correctly to ES5, checkout this link to the online Babel transpiler that contains your sample code.除了您的代码正确编译为 ES5 之外,请查看此链接到包含您的示例代码的在线 Babel 转译器。

Checkout this question similar to yours.结帐这个问题类似于你的。

Yes, it is possible.对的,这是可能的。 Your code should work, you need to check you Babel setup, there must be something wrong with how it's configured.你的代码应该可以工作,你需要检查你的 Babel 设置,它的配置方式一定有问题。

In your example, doSomething is actually a property of the class;在您的示例中, doSomething实际上是该类的一个属性; the type of the property is a function.属性的类型是一个函数。 Here's an example that additionally shows a method, as well as a use of the this keyword:这是一个额外显示方法的示例,以及this关键字的用法:

class SearchForm {

  doSomething = () => {
    console.log('I am a property')
  }

  doSomethingElse() {
    console.log('I am a method')
  }

  doBoth() {
    this.doSomething();
    this.doSomethingElse()
  }
}

const form = new SearchForm();
form.doBoth();

You can check it out live here .你可以在这里查看

Short answer to the post title : Yes you can, but you shouldn't.对帖子标题的简短回答:是的,你可以,但你不应该。 It's weird and bizarre to do that while using ES6 classes (long explanation below).在使用 ES6 类时这样做很奇怪(下面有详细解释)。

Correct solution to your specific use case : Since you want to call this.setState (which I supposed is defined in the parent class) from the object's instance, you should simply rewrite your onSearchChange as a class method:您的特定用例的正确解决方案:由于您想从对象的实例中调用this.setState (我认为它是在父类中定义的),您应该简单地将您的onSearchChange重写为类方法:

onSearchChange(e){
    this.setState({ searchText: e.target.value });
  }

A little bit of theory一点点理论

You are using ES6 classes.您正在使用 ES6 类。 Classes have methods and properties/fields (among many other things).类具有方法和属性/字段(以及许多其他内容)。 Instance methods are like class "functions", which (by definition) have access to the object's internal state.实例方法就像类“函数”,它(根据定义)可以访问对象的内部状态。 Methods can also call other methods, whether they are defined in the same class, or at some parent class in the inheritance chain.方法也可以调用其他方法,无论它们是在同一个类中定义的,还是在继承链中的某个父类中定义的。 There's only one way to write class methods in ES6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#prototype_methods .在 ES6 中只有一种编写类方法的方法: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#prototype_methods

Class properties/fields, on the other hand, are like "variables" which exists in every instance of a class.另一方面,类属性/字段就像存在于类的每个实例中的“变量”。 Every instance have it's own copy of it's properties/variables.每个实例都有它自己的属性/变量副本。 In true OOP languages, instance variables can be declared as private or protected, which makes them completely inaccessible to the outside world.在真正的 OOP 语言中,实例变量可以声明为私有或受保护的,这使得它们完全无法被外界访问。 Class properties/fields, as any javascript variable, can hold ANY value, including.... "functions".类属性/字段,作为任何 javascript 变量,可以保存任何值,包括......“函数”。

When you declare a "function" inside a ES6 class the way you did it, you are not declaring a class method, but declaring a class "field" which it's being assigned an initial value of: an arrow function ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#field_declarations ).当您按照您的方式在 ES6 类中声明“函数”时,您不是在声明类方法,而是声明了一个类“字段”,该字段被分配了初始值:箭头函数( https://developer .mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#field_declarations )。 This is already weird and bizarre, because it is not clear whether you wanted to declare a class method using arrow-function syntax (which is not possible, as previously explained), or you truly wanted to declare a class property/field, and have it automatically initialized to an arrow function... but in this case, why would you want to have every instance of the class with a copy of an arrow function, which, by definition, does't have access to the object's own this ?这已经很奇怪了,因为不清楚您是想使用箭头函数语法声明一个类方法(这是不可能的,如前所述),还是您真的想声明一个类属性/字段,并且有它自动初始化为一个箭头函数......但在这种情况下,为什么要让类的每个实例都带有一个箭头函数的副本,根据定义,它不能访问对象自己的this Wouldn't be better to have that function field declared as static?将该函数字段声明为静态不是更好吗? So you only have one copy of the arrow function?所以你只有一份箭头函数? Or, even better: Why don't you simply move that function to the outside, and use a single reference to that function?或者,甚至更好:为什么不简单地将该函数移到外部,并使用对该函数的单个引用?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM