2017-02-01 6 views
0

私はReactを初めて使用しています。私はReact公式ページhttps://facebook.github.io/react/docs/state-and-lifecycle.htmlの「クイックスタート」に従っている間に奇妙な問題に遭遇しました。このコードでhttp://codepen.io/gaearon/pen/amqdNA?editors=0010[reactjs]匿名関数の定義が等しくない

componentDidMount() { 
    this.timerID = setInterval(
     () => this.tick(), 
     1000 
    ); 
} 

スニペットそれはsetInterval()の最初の引数として無名関数オブジェクトを渡すことで、繰り返し実行されるだろう関数を定義するには、矢印関数の構文を使用しています:あなたはここにCodePenに試すことができます。

私は好奇心を持っていますので、最初の引数として「等価な」関数オブジェクトを渡すためにいくつかの方法を試しました。しかし、私の方法のどれもうまくいかない。

componentDidMount() { 
    this.timerID = setInterval(
     this.tick, // This cannot work in CodePen 

     //function() { 
      //this.tick(); 
     //}, // No 

     //function() { 
      //return this.tick(); 
     //}, // No 

     //() => this.tick(), // This is the official way that works 
     //() => {this.tick();}, // This also works, but notice the difference between this and the last one 
     //() => {this.tick()}, // Also works 
     //() => {return this.tick();}, // Also works, think it equivalent as official one 
     1000 
    ); 
} 

私は純粋なJavascriptのコードスニペットでは、すべてのこれらの方法はsetIntervalが機能するためには有効だと思います。特に、公式文書(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions)のように、矢印関数定義は一般にfunction() { ... }の定義に相当します。しかし、彼らは単にリアクトとバベルで同等ではないようです。

私はBabelによってコンパイルされたJavascriptコードを調べた後、_this2オブジェクトによって異なります。

// Javascript compiled by Babel 
Clock.prototype.componentDidMount = function componentDidMount() { 
    var _this2 = this; 

    this.timerID = setInterval(
     //this.tick // This is the compiled code using one of my way 

     /*function() { 
      this.tick(); 
     },*/ // This is another one 

     function() { 
      return _this2.tick(); 
     }, // This is the compiled code using the official way 

     //function() { 
      //_this2.tick(); 
     //}, // This is the compiled code of another working example 
     1000 
    ); 
}; 

ここで矢印関数の構文を使用する必要があるのはなぜですか。なぜ等価な方法が正しくコンパイルされないのですか?これはReactやBabelのバグですか?

編集:

OK。みんなありがとう! Javascript の "this"についての難しいことは、私が持っているすべての質問にほぼが答えます。今、私は() => {}の定義とfunction() {}の定義に大きな違いがあり、なぜバベルは私が期待したことをしないのかを知っています。

しかし、これは誰かが、コードのこの「簡単に」の行に見てもらえ

this.timerID = setInterval(
    this.tick, // This cannot work in CodePen 
    1000 
); 

に動作しなかった理由、これが答えていないのですか?私はそれが同じ方法で "これ"に関連していないと思いますか?

+1

Funktion(){}になりと()=> {}は同じものではありません。矢印関数はその周辺コンテキスト(this)を保持し、通常の関数は "this"の新しいコンテキストを宣言しています – cyrix

+0

@cyrix Ah!これは本当に重要です! – jlwangPoincare

+0

http://stackoverflow.com/a/41970338/2902660では、関数の_ **コンテキスト** _(つまり、関数定義内の 'this'の値)がどのように評価されるかについて少し説明しています – Pineda

答えて

1

機能(){}と()=> {}はであり、同じものはです。

は考えてみましょう:

#1 
function foo() { 
    console.log('foo'); 
} 

vs: 
#2 
foo =() => { 
    console.log('foo') 
} 

機能#2が新しいコンテキストthis変数を作成していないのに対し、機能#1は、機能に限定し、新しく作成されたコンテキストを持っています。

バベルがすべてを変換するとき、私はそれがこのような何かを行う新しいコンテキストを持っていないように、機能#2ために信じる:

foo =() => { 
    console.log(this.data); 
} 

var this_2 = this; 
function foo() { 
    console.log(this_2.data); 
} 
関連する問題