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


83

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と評価されることです。私はここで何が間違っているのですか?


あなたが持っている理由があるstartにはprototype
xj9 2010年

何にRequest.prototype設定されていますか?
マットボール

私はここで同様の質問をしました:stackoverflow.com/questions/3198264/…そこにはたくさんの役立つリンクがあります。その核心はthis、JavaScriptでは、Javaなどのほとんどのオブジェクト指向言語のように、呼び出されるプロトタイプ関数の「所有者」への定数参照ではないということです。
マークボリンジャー2010年

1
@Matt:リクエストはコンストラクター関数です。Request.prototypeのデフォルトはnew Object()。です。追加したものはすべて、を使用して作成されたオブジェクトのプロパティに自動的になりますnew Request()
Chetan S 2010

@Matt BallRequest.prototypeは、インスタンスがRequest継承する場所です。この場合、おそらくFunctionまたはObjectです。
xj9 2010年

回答:


67

スタート関数をどのように呼び出していますか?

これは機能するはずです(新しいことが重要です)

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

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

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

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

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

私はsetTimeoutを使用しています:var listen = new Request(destination, stay_open); setTimeout(listen.start, 500);
Carson Myers

これは、basicAuthを表現するために渡した関数が同じ出力で機能しない理由を理解しようとしたときに、私の命を救いました。
エジソンスペンサー

またはしますo.start.bind(o)。なぜ機能しないのx = o.start; x()ですか?
theonlygusti

35

関数が高階関数として使用され(引数として渡された)、スコープthisが失われたために、このエラーが発生することがあることを指摘したいと思います。そのような場合、そのような関数をにバインドして渡すことをお勧めしthisます。例えば

this.myFunction.bind(this);

3
良い説明!! それがまさに私が探していたものでした。
vandersondf

1
あなたがどれだけの頭痛を救ったかはわかりません
Native Coder

なぜスコープがthis失われるのですか?
theonlygusti

17

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

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

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

Ninjaインスタンスは同じプロパティを持ってaNinjaいますが、のプロパティにアクセスできないことに注意してくださいenemyNinja。(この部分は本当に簡単でわかりやすいはずです):に何かを追加し始めると、状況は少し異なりますprototype

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

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


6

ES2015では別名ES6classは、のシンタックスシュガーですfunctions

コンテキストを強制的に設定したい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


6
コンストラクターで関数をこれにバインドする必要があります。それ以外の場合はrender、クラスがインスタンス化されるときに1回ではなく、呼び出されるたびにバインドします。また、あなたの例のほとんどは、質問に実際には関連していません。
erich2k8 2018

または、handleChange()
Nitin

0

この質問は答えられました、しかし多分これは誰か他の人がここに来るかもしれません。

またthis、クラスを初期化するときにクラスのメソッドを愚かに分解しようとしたときに、が定義されていないという問題がありました。

import MyClass from "./myClass"

// 'this' is not defined here:
const { aMethod } = new MyClass()
aMethod() // error: 'this' is not defined

// So instead, init as you would normally:
const myClass = new MyClass()
myClass.aMethod() // OK

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.