7

私はまだjsoopで私を悩ませている問題を抱えています-私はそれを悪いことをしていると確信していますが、私はそれを正しく行う方法を得ることができません。

たとえば、私はこのコードを持っています

Auth.prototype.auth = function () {
    var request = new XMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        this.setToken(token);
        this.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

問題は、「request.onloadend」関数のコンテキストから関数setTokenにアクセスできないことです。これは、おそらく「this」への参照を失ったためです。

この問題の解決策は何ですか?どういうわけか「this」変数をこの関数のコンテキストに渡すことはできますか?

ありがとう!

4

6 に答える 6

5

これを行うにはいくつかの方法があります。最も直接的な方法は、必要な値のコピーを保存することです。

Auth.prototype.auth = function () {
    var request = new XMLHttpRequest();
    var self = this; // save "this" value

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        self.setToken(token); // use saved "this" value
        self.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

別の方法は使用することbindです:

request.onloadend = (function () {
  var response = JSON.parse(request.responseText);

  console.log(response);
  if(response.result == 'found') {
    var token = response.token;

    this.setToken(token); // use saved "this" value
    this.isSigned = true;
  } else {
    console.log('Not logged yet.');
  }
}).bind(this);

2番目のアプローチは「よりクリーン」ですが、ブラウザーの互換性の問題があります(IE <9はそれをサポートしていません)。

于 2012-07-09T10:44:37.917 に答える
2

.bind関数:

Auth.prototype.auth = function () {
    var request = new XMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        this.setToken(token);
        this.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }.bind(this); //<-- bound
}
于 2012-07-09T10:45:00.297 に答える
1

外側のスコープでそれへの参照をキャプチャすることができます。私は識別子を使用しましたselfが、名前にもっと意味的な意味を与えてください。

var self = this;
request.onloadend = function () {
  ...
  self.setToken(token);
  ...
};
于 2012-07-09T10:44:29.290 に答える
1

thisコールバックの前にキャプチャします。

Auth.prototype.auth = function () {
    var self = this;

    var request = new XMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        self.setToken(token);
        self.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}
于 2012-07-09T10:44:41.860 に答える
0

thisコールバックの外部のローカル変数に保存します。

Auth.prototype.auth = function () {
    var request = new XMLHttpRequest();
    var _this = this;

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        _this.setToken(token);
        _this.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}
于 2012-07-09T10:45:11.503 に答える
0

正解です。コールバックは、XMLHTTPRequestオブジェクトをコンテキスト(つまり、の値this)として呼び出されます。コールバックのスコープ内でインスタンスにアクセスできるように、インスタンスに別の名前を付ける必要があります。

Auth.prototype.auth = function () {
    var request = new XMLHttpRequest(),
        authInstance = this;

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        authInstance.setToken(token);
        authInstance.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

これが必要な理由の詳細については、別の質問に対するこの回答を参照してください。記述的な変数名を使用するのが一般的に良いと思うので、私はauthInstanceではなくを使用しました。意味をself理解する必要はありませんが、将来誰か(おそらくあなた!)がコードを読むときにあいまいになる可能性があります。authInstanceself

別のオプションはを使用するbindことですが、それはおそらくここで必要以上に複雑です。

于 2012-07-09T10:45:14.087 に答える