web-dev-qa-db-ja.com

反応コンポーネントのコンストラクターで矢印関数を使用できますか?

この質問は Reactを使用する場合、コンストラクターでファットアロー関数またはバインド関数を使用する方が望ましいですか? とは少し異なります。関数をコンストラクターで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つの方法の長所と短所は何ですか?ありがとう。

17
ycavatars

オプション1は一般的に、特定の理由からより望ましいです。

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

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

  doSomething() {}
}
_

プロトタイプのメソッドは拡張が簡単です。子クラスはdoSomethingをオーバーライドまたは拡張できます

_doSomething() {
  super.doSomething();
  ...
}
_

インスタンスプロパティ

_this.doSomeThing = () => {};
_

またはES.nextクラスフィールド

_doSomeThing = () => {}
_

メソッドがプロトタイプで定義されていないため、代わりにsuper.doSomething()を呼び出すことはできません。これをオーバーライドすると、親と子のコンストラクターで_this.doSomeThing_プロパティが2回割り当てられます。

プロトタイプメソッドは、ミックスインテクニックでも使用できます。

_class Foo extends Bar {...}
Foo.prototype.doSomething = Test.prototype.doSomething;
_

プロトタイプメソッドはよりテストしやすくなっています。クラスのインスタンス化の前に、スパイ、スタブ、またはモックすることができます。

_spyOn(Foo.prototype, 'doSomething').and.callThrough();
_

これにより、場合によっては競合状態を回避できます。

10
Estus Flask

あなたはこのようにしたいと思うかもしれません。それはあなたの最初の状況と同じです。ステージ2でバベルを使用します。 (transform-class-properties: http://babeljs.io/docs/plugins/transform-class-properties/ )(preset-stage-2: http:// babeljs。 io/docs/plugins/preset-stage-2 /

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

アプローチ1は私にとって読みやすく、慣用的です。

さらに、コンストラクターの代わりにクラス内でメソッドを宣言すると、メソッドを共有できます。

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の方が低速ですが、パフォーマンスへの影響は無視できます。

Reactのドキュメント で使用されているため、私は単にアプローチ1に進みます。また、アプローチ2を使用する人を見たことがありません。


パフォーマンスをテストするためにいくつかのサンプルを実行しました。最新のChrome(Mac))では、コンストラクターでのメソッドの宣言は、コンストラクターでbindを使用するよりも約90%遅くなっています。

3
CodinCat

これをチェックしてください:

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

バベルトランスパイルを見ることができます

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

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

編集:私はあなたの投稿を少し誤解しましたが、上記はまだ真実で興味深いものです。 @CodinCatは重要なことを指摘します。コンストラクター内で関数を宣言すると、作成時にその関数をオブジェクトに追加するのに時間がかかります(ごくわずかですが)。また、そのクラスのインスタンスが同じdoSomeThingメソッド。

edit2:関数に(this)をバインドすると、実際に上記の問題が発生します。つまり、2つの方法はほとんど同じです。

1
Elliot E