2016-05-11 18 views
1

Ich schreibe ein JavaScript-Programm, das die Methode eines Objekts jede Sekunde ausführt. Die Methode protokolliert nur die Objekteigenschaft "x" und fügt dann eine hinzu."this" gibt zurück undefined

Die Klasse, aus der das Objekt ("Player" genannt) konstruiert wird, heißt "Snake", und die Eigenschaft "x" ist eindeutig als 0 definiert. Wenn ich jedoch meine "everyTick" -Funktion durchführe, protokolliert sie ' nicht definiert'.

Das ist sehr seltsam, weil die Methode auch player.x protokolliert, was genau das tut, was es sollte. Aber wenn ich "this" anstelle von "player" verwende, loggt es undefined. Kann jemand erklären, warum und wie man es repariert?

Hier ist der Code.

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(); 

Es ist wirklich verwirrend, wenn man sieht es einfach so, so ist es hier in CodePen: http://codepen.io/Plygon/pen/jqJZvq?editors=0011

Antwort

2

Dies liegt daran, wenn Sie forever aufrufen, werden Sie einen Verweis auf die player.say Funktion übergeben, aber das Referenz ist nicht auf das Snake Objekt gebunden. Wenn also die Funktion aufgerufen wird, weiß sie nicht, was this ist.

Hier ist ein einfaches Beispiel:

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; 

Was Sie tun müssen, ist die Funktion für das Objekt binden.Die bind Methode der Funktion gibt eine neue Funktion, wo this zu gebunden ist, was auch immer Objekt übergeben Sie bind:

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

Also, wenn Sie tun:

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

Sie sollten in der Lage sein this zu verwenden, wie Sie erwarten innerhalb der say Funktion.

1

Das Problem hier ist die scope von this dies versuchen:

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

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

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

Hier this innerhalb this.say hat einen lokalen Bereich für sagen, Funktion, müssen Sie sich auf this von der parent Funktion beziehen.

+0

Meine Klasse Zeitraum gerade zu Ende gegangen, so kann ich Ihre Antwort jetzt nicht überprüfen, aber dank! – Polygon

1

Das Problem ist hier:

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

Wenn Sie die player.say Funktion senden im Zyklus verwendet werden, können Sie die Verbindung mit dem Objekt player verloren.

dann an der Stelle, wenn die funcion genannt wird, machen Sie einen einfaches Funktionsaufruf, aber keine Methode auf dem Spielerobjekt:

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

das Problem zu lösen, aktualisieren Sie einfach die start Funktion wie diese:

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

die bind() wird eine neue Funktion mit dem Kontext schaffen immer mit derverbundenInstanz beim Aufruf.

This article gibt viele Details über this Stichwort in JavaScript.

1

Das Problem ist, dass Ihre Funktion ihren Kontext verliert (das "Dies").

Die erste Option ist das "this" zu speichern (var self = this).

Eine weitere Option ist binden zu verwenden, ruft oder

Hoffnung anwenden, das hilft :)

Verwandte Themen