2016-02-21 7 views
12

私はES6でClassesの構文を頭の中に入れようとしています。同時に、Bonnie EisenmanのLearning React Nativeを通じてFabricネイティブを学習します。ES6メソッドを呼び出すときのコンテキストをバインドします。コールバックと呼ばれるメソッド内からオブジェクトにアクセスする方法

コールバックがクラス「メソッド」である場合、コールバックでthisにアクセスするという問題が発生しました。私は、コールバックの字句thisの問題がStackOverflowで何度も発生していることを認識しています。たとえば、 How to access the correct `this` context inside a callback?です。

私の研究のオンラインに基づいて私は解決策を見つけました。しかし、私はこれがES6でそれを行う正しい方法であるとは確信していません。

私の問題は、私がしようとしたときに約来たの下に次:

私は少しだけES6クラスの構文とインポート/エクスポート構文の代わりに一致するように本の中の例から変更した
class WeatherProject extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     zip: '' 
    }; 
    } 

    _handleTextChange(event) { 
    console.log(event.nativeEvent.text); 
    this.setState({zip: event.nativeEvent.text}) 
    } 

    render() { 
    return (
     <TextInput 
     style={styles.input} 
     onSubmitEditing={this._handleTextChange}/> 
    ); 
    } 
} 

this_handleTextChangeは未定義です(未定義のプロパティ 'setState'は読み取れません)。私はこれに驚いた。他のオブジェクト指向言語から来ているように、私はこのメソッドが静的メソッドであるかのように動作しているかのように解釈しています。

私はクラスメソッドをスキップし、矢印の表記を使用してこれを解決できました。 onSubmitEditing={event => this.setState({name: event.nativeEvent.text})}。どちらがうまくいくの?私はそれに問題や混乱はありません。

私は本当にクラスメソッドを呼び出す方法を実際に考え出したいと思います。かなりの研究の後、私はそれを次のようにすることによって動作させることができた:onSubmitEditing={this._handleTextChange.bind(this)}。おそらく、私はJavaScriptの基本的な側面を誤解しています(私はJSの初心者です)。しかし、これは私にとっては全く狂っているようです。メソッド内からオブジェクトのコンテキストに実際にアクセスする方法はありませんか?オブジェクトを明示的にバインドせずに...それが呼び出された時点で独自のメソッドですか?

また、var self = this;をコンストラクタに追加して、self.setState_handleTextChangeに呼び出してみました。しかし、あまりにも驚くべきことではないことが分かりました。

コールバックとして呼び出されたときに、メソッドの1つの中からオブジェクトにアクセスする正しい方法は何ですか?

+0

すべての可能な方法はリンク先の質問に記載されています。あなたの意図を最もはっきりと表現するものが最も正しいと主張することができます。 –

答えて

13

React.createClass(ES5)クラスの作成方法には、すべてのメソッドを自動的にthisにバインドするビルトイン機能があります。しかし、ES6にclassesを導入してReact.createClassを移行している間に、他のクラスのこの機能に慣れていないJavaScript開発者にとっては少し混乱するかもしれないし、Reactから他のクラスに移行すると混乱するかもしれない。

そこで、Reactのクラスモデルにこの組み込み関数を組み込んでいないことにしました。

class WeatherProject extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     zip: '' 
    }; 
    this._handleTextChange = this._handleTextChange.bind(this); //Binding to `this` 
    } 

    _handleTextChange(event) { 
    console.log(event.nativeEvent.text); 
    this.setState({zip: event.nativeEvent.text}) 
    } 

しかし、私たちは常にこの事前バインディングを避ける簡単な方法を持っています。うん!あなたはそれを持っています。矢印機能。

class WeatherProject extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     zip: '' 
    }; 
    } 

    _handleTextChange = event => { 
    console.log(event.nativeEvent.text); 
    this.setState({zip: event.nativeEvent.text}) 
    } 

    render() { 
    return (
     <TextInput 
     style={styles.input} 
     onSubmitEditing={this._handleTextChange}/> 
    ); 
    } 
} 

これはすべてリアクションに関するものです。 ES6クラスには、メソッドを明示的にバインドせずにメソッド内からオブジェクトのコンテキストにアクセスする方法が常にあります。

class bindTesting { 
    constructor() { 
    this.demo = 'Check 1'; 
    } 

    someMethod() { 
    console.log(this.demo); 
    } 

    callMe() { 
    this.someMethod(); 
    } 
} 

let x = new bindTesting(); 
x.callMe(); //Prints 'Check 1'; 

しかし、これはJSX式で呼び出すと 'Check 1'と表示されません。

EDIT :: @Okaがクラス本体で、矢印の機能を説明したようにはバベルのようなコンパイラ/ polyfillsでES7 +の機能と使用可能です。あなたはこの機能をサポートtranspilerを使用していない場合、私達はちょうど上記のようthisに結合するか、またはこのような新しいBaseComponentを書く(悪い考えです)

class BaseComponent extends React.Component { 
_bind(...methods) { 
    methods.forEach((method) => this[method] = this[method].bind(this)); 
} 
} 

class ExampleComponent extends BaseComponent { 
constructor() { 
    super(); 
    this._bind('_handleTextChange', '_handleClick'); 
} 
// ... 
} 
+2

'class'ボディの矢印機能はES7の提案であり、Babelのようなトランスパイライザでは究極のものとみなされています。 – Oka

+0

@Oka Yeah! True – Prasanth

+0

@gunshotオブジェクトコンテキストが正しくバインドされたバージョンになるように、コンストラクタ内のメソッドにアクセスするために変数を変更するのは、まさに私が探していたソリューションのタイプですが、自分では解決できませんでした。ありがとうございました。私は '' 'this._handleTextChange = this._handleTextChange.bind(this);を使用します。 '' '。独創的! – rod

6

を離れES6から断ち切る、と反応することができます通常の古いJavaScriptでは、オブジェクトのメソッドを渡すときには、関数の関数ではなく、関数自体を参照するだけです。

任意の呼び出し機能が正常に機能を呼び出すことで、暗黙のthisを使用するように選択することができ、またはそれも.call.apply、または.bindを使用してコンテキストを変更することを選択できます。で何が起こっている

var O = { 
 
    foo: function() { 
 
    console.log(this); 
 
    }, 
 
    bar: 51 
 
}; 
 

 
O.foo(); // `this` is O, the implicit context, inferred from the object host 
 

 
var foo = O.foo; 
 

 
foo(); // `this` is is the global object, or undefined in Strict Mode

、後でいくつかの時間を実行されますイベント・エミッターに _handleTextChange 機能を渡しています。イベントエミッタは、 メソッドとして関数を受け取ったことを知らない。それだけでそれを実行します。

var O = { 
 
    foo: function (event) { 
 
    console.log(this); 
 
    console.log(event); 
 
    }, 
 
    bar: 51 
 
}; 
 

 
function invoke (func) { // the function reference held by O.foo is now held by `func` 
 
    func('some param'); // it has no idea as to what the contextual `this` is bound to, maybe its implicitly global, maybe its explicitly bound, maybe its undefined 
 
} 
 

 
invoke(O.foo); 
 

 
invoke(O.foo.bind(O)); // A copy of the function with the context explicitly bound

コンテキストの共有を見てみましょう:

function foo() { 
 
    console.log(this.a); 
 
} 
 

 
// Both object hold references to the foo function 
 
var O = { foo : foo, a : 5 }, 
 
    O2 = { bar : foo, a : 1 }; 
 

 
O.foo(); // implicit `this` from O 
 
O2.bar(); // implicit `this` from O2 
 

 
var Z = { a : 23 }; 
 

 
O.foo.call(Z); // explicit `this` from Z

あなたはこれらの例で任意に複雑に得ることができます。

3

私はJavaScriptの基本的な側面(私はJSの初心者です)と誤解しているかもしれませんが、これは私にとってはまったく狂っているようです。メソッド内からオブジェクトのコンテキストに実際にアクセスする方法はありませんか?オブジェクトを明示的にバインドせずに...それが呼び出された時点で独自のメソッドですか?

まあ、「メソッド」はが所有しています。はjavascriptのオブジェクトではありません。すべての関数はファーストクラスの値(オブジェクト)であり、オブジェクトやクラスの「部分」ではありません。関数は、関数が呼び出された方法に応じて、呼び出されたときに

this valueの結合が起こります。メソッド表記法を使用する関数呼び出しでは、受信オブジェクトにthisが設定され、イベントリスナーの呼び出しには現在のイベントターゲットにthisが設定され、通常の関数呼び出しにはundefinedしかありません。

インスタンス上でメソッドにアクセスしている場合、それは本当に、その後と呼ばれ、受信機に動的にバインドされている機能を、生み出すだけの標準的なプロトタイプの継承プロパティへのアクセスです。

インスタンスをイベントリスナーのときにメソッドとして呼び出す場合は、これを行う関数、つまり「バインド」メソッドを明示的に作成する必要があります。 ES6では、通常これには矢印表記が優先されます。

関連する問題