33

プレーヤーのリスポーンを制御する関数内にsetTimeoutを定義しています(ゲームを作成しています)。

var player = {
    ...
    death:(function() {
        this.alive = false;
        Console.log("death!");
        var timer3 = setTimeout((function() {
            this.alive = true;
            Console.log("alive!");
        }),3000);
    }),
    ...
}

それが実行されるとき、私はコンソールで「死!」と読みました。そして3秒後に「生きている!」ただし、実際にtrueに戻されることはありません。コンソールにalive書き込むと、が返されるためです。どうして私は「生きている」を見ることができます!しかし、変数がtrueに戻されることはありませんか?player.alivefalse

4

5 に答える 5

46

に注意する必要がありthisます。this外側のスコープで変数にを割り当てる必要があります。thisキーワードは常に現在のスコープを参照します。thisこれは、何かをラップするたびに変更されfunction() { ... }ます。

var thing = this;
thing.alive = false;
Console.log("death!");
var timer3 = setTimeout((function() {
    thing.alive = true;
    Console.log("alive!");
}),3000);

これはあなたにより良い成功を与えるはずです。

アップデート2019-10-09:元の答えは正しいですが、JavaScriptの最近のバージョンで別のオプションが利用できるようになりました。をfunction使用する代わりに、変更しない矢印関数を使用できますthis

this.alive = false;
Console.log("death!");
var timer3 = setTimeout(() => {
    this.alive = true;
    Console.log("alive!");
}), 3000);

これは、現在のすべてのブラウザの一部であるES6以降でサポートされていますが、IE(もちろん)だと思います。最新のフレームワークを使用してBabelなどを介してプロジェクトを構築している場合、フレームワークは、これがどこでも期待どおりに機能することを確認する必要があります。

于 2012-07-30T01:21:13.207 に答える
22

これthisは、setTimeoutハンドラーでがを参照しているためです。これは、ハンドラーの外部でwindow参照されている値とはおそらく同じではありません。this

外側の値をキャッシュして、内側で使用できます...

var self = this;

var timer3 = setTimeout((function() {
    self.alive = true;
    Console.log("alive!");
}),3000);

...またはES5を使用できますFunction.prototype.bind...

var timer3 = setTimeout((function() {
    this.alive = true;
    Console.log("alive!");
}.bind(this)),3000);

...レガシー実装をサポートしている場合でも、にシムを追加する必要がありますFunction.prototype


...またはES6環境で作業している場合...

var timer3 = setTimeout(()=>{
    this.alive = true;
    Console.log("alive!");
},3000);

inのバインディングがないthisArrow functionsためです。

于 2012-07-30T01:21:31.407 に答える
10

誰かがこれを読んだ場合に備えて、新しいjavascript構文を使用すると、スコープを「bind」を使用して関数にバインドできます。

window.setTimeout(this.doSomething.bind(this), 1000);
于 2016-02-22T14:45:56.883 に答える
5

おそらくthis、タイムアウトコールバックに保存されていないためです。試す:

var that = this;
...
var timer3 = setTimeout(function() {
    that.alive = true;
    ...

更新(2017) -またはラムダ関数を使用します。これは暗黙的にキャプチャしthisます:

var timer3 = setTimeout(() => {
    this.alive = true;
    ...
于 2012-07-30T01:21:39.120 に答える
5

ES6関数構文では、「this」のスコープはsetTimeout内で変更されません。

var timer3 = setTimeout((() => {
    this.alive = true;
    console.log("alive!");
}), 3000);
于 2017-08-03T21:20:21.663 に答える