2016-05-11 13 views
1

私は毎秒オブジェクトのメソッドを実行するJavaScriptプログラムを作成しています。このメソッドは、オブジェクトのプロパティ "x"を記録し、それに1を加えます。"this"は未定義です

オブジェクト(「プレイヤー」と呼ばれる)が構築されるクラスは「スネーク」と呼ばれ、プロパティ「x」は明確に0と定義されます。ただし、「everyTick」関数を実行すると、未定義'。

これは非常に奇妙です。これは、メソッドがplayer.xをログに記録するためです。しかし、 "player"の代わりに "this"を使用すると、定義されていません。誰もがなぜそれを修正する方法を説明することができますか?

ここにコードがあります。

var FPS = 1; 
var toBeRun = { 
    func: function() {}, 
    index: 0 
}; 

function tickFunction(func) { 
    this.func = function() { 
    func(); 
    } 
} 

function everyTick() { 
    toBeRun.func() 
    setTimeout(function() {everyTick();}, 1000/FPS); 
} 

function forever(func) { 
    toBeRun = new tickFunction(func); 
} 


function Snake() { 
    this.x = 0; 

    this.say = function() { 
    console.log(player.x); 
    console.log(this.x); 

    player.x++; 
    this.x++; 
    } 
} 


var player = new Snake(); 

function start() { 
    forever(player.say); 
} 

everyTick(); 

あなたはちょうどそのようにそれを見るとき、それは、本当に混乱しますので、ここではCodePenである: http://codepen.io/Plygon/pen/jqJZvq?editors=0011

答えて

2

foreverを呼び出すと、player.say関数への参照が渡されますが、その参照はSnakeオブジェクトにバインドされていないためです。だから関数が呼び出されると、それは何かがわからないthisです。ここで

は簡単な例です:あなたがする必要がどのような

function Person(name) { 
    this.name = name; 
    this.say = function() { 
     return this.name; 
    }; 
} 

var p = new Person('Bob'); 
console.log(p.say()); // Bob 
var fn = p.say; 
console.log(p.say()); // undefined; 

は、オブジェクトに関数をバインドしています。あなたがしなければ、そう

var boundFn = p.say.bind(p); 
console.log(boundFn()); // Bob 

:関数のbind方法はthisbindにお渡しどんなオブジェクトにバインドされている新しい関数を返す

forever(player.say.bind(player)); 

あなたが期待するようthisを使用することができるはずですsay関数内に移動します。

1

ここでの問題は、thisscopeはこの試みる次のとおりです。ここで

function Snake() { 
    this.x = 0; 
    var parent = this; 

    this.say = function() { 
    console.log(player.x); 
    console.log(parent.x); 

    player.x++; 
    parent.x++; 
    } 
} 

thisthis.sayの中にはローカルスコープがあり、parent関数のthisを参照する必要があります。

+0

私のクラス期間を

希望を呼び出すか、適用するだけで終わったので、私は今、あなたの答えを確認することはできませんが、ありがとう! – Polygon

1

問題はここにある:

function start() { 
    forever(player.say); 
} 

あなたはサイクルで使用するplayer.say機能を送信すると、あなたはplayerオブジェクトとの接続を失いました。

その後funcionが呼び出された場所で、あなたは簡単な関数呼び出しではなく、選手オブジェクト上方法作る:

function tickFunction(func) { 
    this.func = function() { 
    func(); // simple function invocation, which has `this` as `undefined` 
    } 
} 

がちょうどstartを更新し、問題を解決するためにはこれと機能:

function start() { 
    forever(player.say.bind(player)); 
} 

bind()は常に0123に接続されているコンテキストに新しい関数を作成します。インスタンスを呼び出します。

This articleはJavaScriptのthisについての詳細をたくさん掲載しています。

1

問題は、関数がコンテキスト( "this")を失うことです。

最初のオプションは "this"(var self = this)を保存することです。

別のオプションは、バインドを使用することであるが、このことができます:)

関連する問題