Klasse erzeugen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Klasse erzeugen

    Hallo miteinander,

    das Klassenthema in JS ist mir auch neu und dazu hätte ich eine Frage:
    Seither war der Code Ausschnitt um ein Websocket Objekt zu erzeugen so:

    Quellcode

    1. ws=new WebSocket('wss://ws.server...);
    2. ws.onopen = function(evt) {
    3. onOpen(evt)
    4. };
    5. ws.onmessage = function(msg) {
    6. onMessage(msg)
    7. };
    8. onOpen = function(evt) {...}
    9. onMessage = function(msg){....}
    Alles anzeigen

    Jetzt möchte ich das ganze in eine Klasse packen und bin soweit:

    Quellcode

    1. class UserChart{
    2. constructor(){
    3. this.ws = new WebSocket('wss://ws.binaryws.com/websockets/v3?app_id=2796');
    4. ws.onopen = function(evt) {
    5. onOpen(evt)
    6. }
    7. ws.onmessage = function(msg) {
    8. onMessage(msg)
    9. }
    10. }
    11. onOpen(){...}
    12. onMessage(){....}
    13. }
    Alles anzeigen
    Und das funktioniert nicht. Das websocket Objekt erstellt er noch aber die darunter liegenden Verweise auf die Funktionen des ws Objekts "ws.onopen = function...." resultieren in syntax error.
    Was mache ich falsch?

    Vielen Dank und Grüße
  • Du versuchst zwei Funktionen als Eigenschaften namens onopen und onmessage auf eine nicht vorhandene Variable namens ws zu definieren, was sobald der Code ausgeführt also eine Instanz der Klasse angelegt werden soll, in einem ReferenceError resultiert.

    Da du die WebSocket-Verbindung unter this.ws abspeicherst, musst du diese Variable auch für das Anlegen der Funktionen verwenden. Außerdem musst du noch das this der Klasse in einer anderen Variable that speichern, damit du so auch innerhalb der Funktionen onopen und onmessage auf das this der Klasse und nicht auf deren eigenen this zugreifst, was du benötigst wenn du innerhalb dieser Funktionen die klasseneigenen Funktionen onOpen() und onMessage() aufrufen möchtest.

    Folgendermaßen funktioniert es korrekt:

    JavaScript-Quellcode

    1. class UserChart {
    2. constructor() {
    3. var that = this;
    4. this.ws = new WebSocket('wss://ws.binaryws.com/websockets/v3?app_id=2796');
    5. this.ws.onopen = function(evt) {
    6. that.onOpen(evt)
    7. }
    8. this.ws.onmessage = function(msg) {
    9. that.onMessage(msg)
    10. }
    11. }
    12. onOpen(){ }
    13. onMessage(){ }
    14. }
    Alles anzeigen
    Grüße,
    NodeCode

    NodeCode.de
  • Super, vielen Dank so gehts,
    Jede Menge this und thats dabei. Ich habe das Schlüsselwort this deswegen verwendet weil die ganzen Klassenbeispiele das auch so machen.
    Wirklich verstanden habe ich nicht warum das Schlüsselwort this dabei verwendet wird und was den Unterschied ausmacht wenn ich es nicht verwenden würde.
    Da fehlt mir noch das Wissen um die Bedeutung von this. Ich dachte immer das es quasi ein Anzeiger auf das eigene Objekt ist.
    Wenn du mir da etwas auf die Sprünge helfen könntest wäre toll oder eine entsprechende Referenz die es genau erklärt.

    Danke und Grüße
  • Ja, this referenziert in diesem Fall auf das eigene Objekt der Funktion. Innerhalb von constructor() ist das die Klasse UserChart, innerhalb der Funktion this.ws.onopen() jedoch dann das WebSocket-Objekt this.ws, deshalb die Variable that, damit du so die klasseneigenen Funktionen innerhalb der Funktionen eines anderen Objektes aufrufen kannst.

    Wenn du auf das WebSocket-Objekt nicht von außerhalb der Instanz zugreifen möchtest könntest du das this bei der WebSocket-Verbindung auch weglassen und die Variable ws ganz normal über var definieren. Über new UserChart().ws hättest du dann also beispielsweise keinen Zugriff mehr.

    Zum Schlüsselwort this siehe am besten hier.
    Grüße,
    NodeCode

    NodeCode.de
  • Ich möchte hierzu auch mal was sagen.


    Zu "Klassen"

    Zuerst Mal: JavaScript kennt keine OOP (im Sinne jeder anderen Programmiersprache).

    Allerdings trifft der Begriff "Objekt orientiere Programmierung" auf keine andere Sprache so sehr zu wie auf JavaScript, denn alles (außer Primitives) ist in JS ein Objekt. Auch Funktionen sind in JS "ausführbare Objekte". Mit dem class-Keyword erzeugt man keine Klasse, denn die gibt es nicht in JS, sondern eine Konstruktorfunktion. Es gibt keine Vererbung sondern die Prototyp-Delegation. Daher sind Klassen auch nicht notwendig.

    Das Thema der Objekterstellung und Prototyp-Delegation gehört zu den komplexesten, schwersten und wichtigsten Themen in JS. Ich verweise hier mal einfach auf MPJ.


    Zu deinem Beispiel

    Du kannst dieses that (manchmal auch als self bezeichnet) einfach los werden, wenn du anstelle der deklarativen Funktion eine Arrow-Funktion verwendest. Eine der wichtigsten Eigenschaften von Arrow-Funktionen ist nämlich, dass sie das this nicht neu binden.

    JavaScript-Quellcode

    1. class UserChart {
    2. constructor() {
    3. this.ws = new WebSocket('wss://ws.binaryws.com/websockets/v3?app_id=2796')
    4. this.ws.onopen = evt => this.onOpen(evt)
    5. this.ws.onmessage = msg => this.onMessage(msg)
    6. }
    7. onOpen(){ /* "on open" event handler */ }
    8. onMessage(){ /* "on message" event handler */ }
    9. }


    Zudem scheinst du die beiden Eventhandler nur intern und nur einmalig zu gebrauchen. Wozu also Methoden definieren? Schreib die Handler doch mit in den Konstruktor.

    JavaScript-Quellcode

    1. class UserChart {
    2. constructor() {
    3. this.ws = new WebSocket('wss://ws.binaryws.com/websockets/v3?app_id=2796')
    4. this.ws.onopen = evt => { /* "on open" event handler */ }
    5. this.ws.onmessage = msg => { /* "on message" event handler */ }
    6. }
    7. }
  • Da sind sie wieder, die Arrow Funktionen die mir jetzt schon ein paar mal begegnet sind - ich aber immer noch nicht richtig verstanden habe.
    Aber auch ein sehr interessanter Lösungsansatz, vielen Dank dafür.

    Beide Funktionen in den Konstruktor zu schreiben würde nur für die onOpen Methode Sinn machen. Die onMessage kommt eigentlich bei jedem Konnekt via Websocket zum Einsatz. Für Rückmeldungen, Fehler etc.

    Es mag sein dass die class in JS keine echte Klasse ist, aber durch den Begriff ist es für mich schon mal einfacher ein Objekt zu formulieren dass Eigenschaften und Methoden besitzt die es ausführen kann. Wahrscheinlich braucht es ein gestandener Coder nicht aber mir kam die Möglichkeit in Klassen zu denken sehr entgegen.
  • Frika schrieb:

    Da sind sie wieder, die Arrow Funktionen die mir jetzt schon ein paar mal begegnet sind - ich aber immer noch nicht richtig verstanden habe.
    Arrow-Funktionen unterscheiden sich im wesentlichen durch 3 Punkte von deklarativen Funktionen:
    • Das this wird nicht neu gebunden
    • Sie sind immer anonym
    • Es gibt kein hoisting (die Definition muss vor der Verwendung erfolgen)

    JavaScript-Quellcode

    1. // Ansonsten ist
    2. function myFunction(a, b) {
    3. return a + b
    4. }
    5. // identisch zu
    6. const myFunction = (a, b) => {
    7. return a + b
    8. }


    Zusätzlich gibt es noch Möglichkeiten zur verkürzten Schreibweise:
    • Wenn nur ein Parameter angegeben wird, kann man die "()" weglassen: a => { return a + a }
    • Steht im Funktionskörper nur ein einziger Ausdruck, können die "{}" weggelassen werden. Das Ergebnis des Ausdrucks wird in diesem Fall der Returnwert: (a, b) => a + b

    Frika schrieb:

    Beide Funktionen in den Konstruktor zu schreiben würde nur für die onOpen Methode Sinn machen. Die onMessage kommt eigentlich bei jedem Konnekt via Websocket zum Einsatz. Für Rückmeldungen, Fehler etc.
    Auch die "onMessage"-Funktion muss nur ein einziges Mal deklariert und zugewiesen werden. Sie ist schließlich ein Event-Handler. Sie führt sich dennoch mit jedem "message"-Event aus. Du hast Sie schließlich auch in der this.ws.onmessage-Property abgelegt. Sie wird also nicht plötzlich verloren gehen. Wozu also noch eine Referenz in UserChart.prototype.onMessage erzeugen?



    Frika schrieb:

    Es mag sein dass die class in JS keine echte Klasse ist, aber durch den Begriff ist es für mich schon mal einfacher ein Objekt zu formulieren dass Eigenschaften und Methoden besitzt die es ausführen kann.
    Ich kann ehrlich gesagt keinen Zusammenhang zwischen Klassen und Objekten erkennen. Kann es sein, dass du aus einer Klassen-orientierten Sprache wie Java kommst?

    Ein einzelnes Objekt mit Methoden anzulegen ist auch nicht so schwer:

    JavaScript-Quellcode

    1. const myObject = {
    2. name: 'Batman',
    3. sayHello() {
    4. console.log(`Ich bin ${this.name}`)
    5. }
    6. }
    7. myObject.sayHello()
    Die Konstruktorfunktionen ("class"-Keyword) bringen nur noch den Vorteil der Prototyp-Delegation ein.


    Jeremy Keith schrieb:

    Java is to JavaScript as ham is to hamster.
  • Herzlichen Dank für die ausführlichen Erklärungen, und ja es stimmt ich habe mich auch schon einige Zeit mit Java beschäftigt und deswegen uach einen leichteren Zugang ziu dem Begriff Klasse. Sicherlich ist es auch möglich den von dir beschriebenen Weg mit den Funktionen zu gehen um "Objekte" zu definieren die dann instanziiert werden können.
    Auch die Arrow Funktionen sind sehr interessant, im besonderen mit der this Angelegenheit. Das vereinfacht mein Plan an der Stelle.
    Die onOpen Funktion brauche ich in der Klasse noch an einer anderen Stelle (bei einem reOpen der WS Verbindung), deswegen ist sie ausserhalb des Konstruktors ganz gut aufgehoben, denke ich.
    Das mit dem hoisting erscheint mir jetzt erst einmal nicht als Vorteil weil man dann alles definieren muss bevor man es aufrufen kann. Zwecks Übersicht und Sortierung des Quellcode, meine ich, ist das nicht so geschickt. Wahrscheinlich gibt es aber etliche Vorteile die diesen Umstand rechtfertigen

    Vielen Dank nochmals , Grüße
  • Neu

    Ich hänge das mal an die Klassen Frage an weil es ein Problem ist dass eine Klasse betrifft.

    ich würde gerne innerhalb der Klasse eine Methode zeitgesteuert ausführen, ist das möglich? Der Aufruf des Timers geschieht aber auch innerhalb einer anderen Methode in der Klasse.
    Ich habe es bereitsso versucht

    Quellcode

    1. setTimeout(function(){this.orderFin(js.buy.contract_id)}, 60000);
    aber da meckert der Compiler weil es innerhalb der Klasse nur Methoden gibt und keine Funktionen. Lasse ich im setTimout Aufruf das function() vorne herum weg
    meckert er auch weil er er möchte gerne functionen aufrufen.
    Denke ich falsch oder gibt es da eine Möglichkeit, eben eine Methode innerhalb der Klasse zeitgesteuert aufzurufen.
    Vielen Dank und Grüße