2013-10-23 4 views
5

In dem folgenden Code, wenn somethingUseful.thisUsefulThing von setTimeout aufgerufen wird, kann es Referenz?JavaScript: Ein Funktionsverzeichnis: Kann eine Funktionsreferenz aus ihrem Wörterbuch funktionieren?

var somethingUseful = { 
    thisUsefulThing: function() { 
    this.thatUsefulThing(); 
    }, 

    thatUsefulThing: function() { 
    console.log("I am useful!"); 
    } 
} 

setTimeout(somethingUseful.thisUsefulThing, 1000); 

Gerade jetzt, ich bin immer diese Fehlermeldung:

Uncaught TypeError: Object [object global] has no method 'thatUsefulThing' 
+6

Was meinen Sie "Geltungsbereich des globalen" vs "Umfang des Objekts"? Ihr Code funktioniert wie geschrieben. – user2736012

+1

Bedenke nur, dass wenn du 'object.method()' benutzt, der Wert von 'this' in' method' eine Referenz auf 'object' wird. Es spielt keine Rolle, wo und wann das Objekt und die Methode erstellt wurden. Alles, was zählt, ist * wie * du die Methode nennst. Setzen Sie dieselbe Methode auf ein anderes Objekt, rufen Sie sie von diesem Objekt ab, und der Wert von this bezieht sich auf das neue Objekt. 'var o = {thatUsefulThing: function() {console.log (" Ich bin auch nützlich! ");}}; o.foo = somethingUseful.thisUsefulThing; o.foo(); // Ich bin auch nützlich. – user2736012

+0

Dort habe ich es bearbeitet, um den Fehler, dem ich gerade begegne, direkt wiederzugeben. – Synthead

Antwort

3

einfach Um Ihre Frage zu beantworten, YES, thisUsefulThing CAN thatUsefulThing Zugriff

Aber wie Ihr Code zur Zeit läuft, 'this' ist nicht wirklich global, es ist ein Verweis auf etwas, das für alle direkten Nachkommen selbst nützlich ist.

Wenn ich mit wörtlichen Objekte arbeite, ich sie in der Regel nach Namen verweisen, anstatt mit ‚this‘, so in Ihrem Fall würde ich ‚this.thatUsefulThing()‘ mit somethingUseful.thatUsefulThing replace()

Warum ? Weil es sowieso global funktioniert!

EDIT:

Als plalx auf meine Antwort in seinem Kommentar darauf hingewiesen, Best Practices diese Klasse für die Implementierung (mit einem Beispiel Klassenmitglied) würde funktionelle Klassen/Prototypen verwenden und wie folgt aussehen:

function SomethingUseful() { 
    this.member = 'I am a member'; 
} 
SomethingUseful.prototype.thisUsefulThing = function() { 
    this.thatUsefulThing(); 
} 
SomethingUseful.prototype.thatUsefulThing = function() { 
    console.log('I am useful, and ' + this.member); 
} 
usefulObject = new SomethingUseful(); 

usefulObject.thisUsefulThing(); // logs fine with access to this.member 
setInterval(usefulObject.thisUsefulThing.bind(usefulObject), 1000); // has access to this.member through bind() 
+1

Ja, das dachte ich auch, besonders wenn der Code, den ich gepostet habe, wirklich funktioniert hat, hahaha. Nimm dir eine Sekunde Zeit, um über meine bearbeitete Frage zu schauen, wenn du möchtest. Und ja, JavaScript ist ein (viel überfälliges) neues meine Liste. – Synthead

+1

Um Ihre Frage zu lösen, würde ich immer noch 'this.thatUsefulThing()' in 'somethingUseful.thatUsefulThing()' ändern. – Miles

1

Binden Sie einfach den this Wert an somethingUseful.

setTimeout(somethingUseful.thisUsefulThing.bind(somethingUseful), 1000); 
+0

Wahrscheinlich besser, einfach den schlechten Verweis auf 'this' zu beheben, anstatt zu binden. – Miles

+0

@ ich-leben-in-einem-storm-drain Eigentlich denke ich, es ist ganz im Gegenteil. Sich auf einen Variablennamen zu verlassen, ist ziemlich unflexibel, fehleranfällig und weit davon entfernt, DRY zu sein. – plalx

+0

Denken Sie darüber nach: Wenn Sie verbindlich sind, geben Sie den Variablennamen bereits zweimal und die Methoden und Klammern erneut ein. Hört sich ziemlich weh an. – Miles