web-dev-qa-db-ja.com

「this」はJavaScriptクラスメソッドでは定義されていません

私はJavaScriptが初めてです。私が実際に行った限りでは、既存のコードを微調整し、jQueryを少し書いただけです。

現在、属性とメソッドを使用して「クラス」を作成しようとしていますが、メソッドに問題があります。私のコード:

function Request(destination, stay_open) {
    this.state = "ready";
    this.xhr = null;
    this.destination = destination;
    this.stay_open = stay_open;

    this.open = function(data) {
        this.xhr = $.ajax({
            url: destination,
            success: this.handle_response,
            error: this.handle_failure,
            timeout: 100000000,
            data: data,
            dataType: 'json',
        });
    };

    /* snip... */

}

Request.prototype.start = function() {
    if( this.stay_open == true ) {
        this.open({msg: 'listen'});
    } else {

    }
};
//all console.log's omitted

問題は、Request.prototype.startthisは未定義であるため、ifステートメントはfalseと評価されます。ここで何が間違っていますか?

61
Carson Myers

どのように開始関数を呼び出していますか?

これは動作するはずです(newがキーです)

_var o = new Request(destination, stay_open);
o.start();
_

Request.prototype.start()のように直接呼び出すと、thisはグローバルコンテキスト(ブラウザーではwindow)を参照します。

また、thisが未定義の場合、エラーになります。 if式はfalseと評価されません。

更新thisオブジェクトは宣言に基づいて設定されるのではなく、invocationによって設定されます。つまり、関数プロパティを_x = o.start_などの変数に割り当ててx()を呼び出すと、start内のthisoを参照しなくなります。 setTimeoutを実行すると、これが起こります。動作させるには、代わりに次のようにします:

_ var o = new Request(...);
 setTimeout(function() { o.start(); }, 1000);
_
55
Chetan Sastry

JavaScriptのOOPは少しファンキー(またはかなり)で、慣れるのに少し時間がかかります。最初に覚えておく必要があるのは、クラスがないそして、クラスの観点から考えると、あなたをつまずかせる可能性がありますコンストラクター(クラス定義に相当するJavaScript)にアタッチされたメソッドを使用するには、オブジェクトをインスタンス化する必要があります。

Ninja = function (name) {
    this.name = name;
};
aNinja = new Ninja('foxy');
aNinja.name; //-> 'foxy'

enemyNinja = new Ninja('boggis');
enemyNinja.name; //=> 'boggis'

Ninjaインスタンスには同じプロパティがありますが、aNinjaenemyNinjaのプロパティにアクセスできません。 (この部分は本当に簡単/簡単なはずです)prototypeに何かを追加し始めると、物事が少し異なります:

Ninja.prototype.jump = function () {
   return this.name + ' jumped!';
};
Ninja.prototype.jump(); //-> Error.
aNinja.jump(); //-> 'foxy jumped!'
enemyNinja.jump(); //-> 'boggis jumped!'

これを直接呼び出すと、コンストラクターがインスタンス化されたときにのみthisが正しいオブジェクト(「クラス」)を指すため、エラーがスローされます(そうでない場合はブラウザーのグローバルオブジェクトwindowを指します)

15
xj9

ES2015 a.k.a ES6では、classfunctionsの構文糖です。

thisのコンテキストを強制的に設定する場合は、bind()メソッドを使用できます。 @chetanが指摘したように、呼び出し時にコンテキストも設定できます!以下の例を確認してください。

_class Form extends React.Component {
constructor() {
    super();
  }
  handleChange(e) {
    switch (e.target.id) {
      case 'owner':
        this.setState({owner: e.target.value});
        break;
      default:
    }
  }
  render() {
    return (
      <form onSubmit={this.handleNewCodeBlock}>
        <p>Owner:</p> <input onChange={this.handleChange.bind(this)} />
      </form>
    );
  }
}
_

ここでは、handleChange()内のコンテキストをFormに強制しました。

4
Nitin