我可以在反应组件的构造函数中使用箭头函数吗?

Can I use arrow function in constructor of a react component?

这个问题与类似,但有一点不同。您可以在构造函数中将函数绑定到 this,或者只在构造函数中应用箭头函数。请注意,我的项目中只能使用 ES6 语法。

1.

class Test extends React.Component{
  constructor(props) {
    super(props);

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

  doSomething() {}
}

2.

class Test extends React.Component{
  constructor(props) {
    super(props);

    this.doSomeThing = () => {};
  }
}

这两种方式的优缺点是什么?谢谢

我想你可能想要这样。你的第一种情况也是一样的。 它将在第 2 阶段与 babel 一起工作。 (转换-class-属性:http://babeljs.io/docs/plugins/transform-class-properties/) (预设阶段 2:http://babeljs.io/docs/plugins/preset-stage-2/

class Test extends React.Component{
  constructor(props) {
    super(props);
  }
  doSomeThing = () => {}
}

看看这个:

https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&targets=&browsers=&builtIns=false&debug=false&code=class%20Dog%20%7B%0A%20%20constructor()%20%7B%0A%20%20%20%20%0A%20%20%20%20this.cat%20%3D%20_%3D%3E%20%7B%0A%20%20%20%20%20%20this%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D

我们可以看到 babel transpiles

this.doSomeThing = () => { this };

进入

var _this = this;
this.doSomething = function() { _this }

编辑:我稍微看错了你的post,但上面的内容仍然真实有趣。 @CodinCat 指出了重要的事情:在构造函数中声明一个函数意味着在创建对象时需要时间(尽管很少)将该函数添加到对象中,并且还可能占用内存,因为 class 不共享相同的 doSomeThing 方法。

edit2:将 (this) 绑定到函数实际上会导致我上面列出的确切问题。也就是说这两种方法几乎完全一样。

方法 1 对我来说更易读,也更惯用。

此外,在class而不是构造函数中声明方法,方法可以共享。

class Foo {
  test() {}
}

const f1 = new Foo()
const f2 = new Foo()
f1.test === f2.test // true

在方法 2 中,您将在每次创建新实例时声明所有方法:

class Foo {
  constructor() {
    this.test = () => {}
  }
}

const f1 = new Foo()
const f2 = new Foo()
// the method is not shareable
f1.test === f2.test // false

理论上方法2速度较慢,但​​对性能的影响应该可以忽略不计。

我只选择方法 1,因为它在 React documentation 中使用,而且我从未见过有人使用方法 2。


我只是 运行 一些样本来测试性能。在最新的 Chrome (Mac) 中,在构造函数中声明方法比在构造函数中使用 bind 慢大约 90%。

出于某些原因,选项 1 通常更可取。

class Test extends React.Component{
  constructor(props) {
    super(props);

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

  doSomething() {}
}

原型方法更易于扩展。 Child class 可以用

覆盖或扩展 doSomething
doSomething() {
  super.doSomething();
  ...
}

当实例属性

this.doSomeThing = () => {};

或ES.nextclass字段

doSomeThing = () => {}

被使用,调用 super.doSomething() 是不可能的,因为该方法没有在原型上定义。覆盖它将导致在 parent 和 child 构造函数中分配 this.doSomeThing 属性 两次。

混合技术也可以使用原型方法:

class Foo extends Bar {...}
Foo.prototype.doSomething = Test.prototype.doSomething;

原型方法更容易测试。它们可以在 class 实例化之前被监视、存根或模拟:

spyOn(Foo.prototype, 'doSomething').and.callThrough();

这可以在某些情况下避免竞争条件。