Manöverkritik: OOP in JS
Matthias Scharwies
- javascript
- selfhtml-wiki
Guten Morgen!
@Felix Riesterer hatte im Februar einen Einstieg in die OOP gestartet, der hier diskutiert wurde:
Molilys Artikel-Reihe "Organisation von JavaScripten" von 2006 wird dieses Jahr 15. Sie war auch nie als durchgängiger Kurs bestimmt.
Ich habe jetzt einmal eine überarbeitete Version veröffentlicht: JavaScript/Tutorials/OOP
Ich würde neben dem Einstieg im Kurs in sich geschlossene Kapitel wie this und Objektabfragen behalten; dazu könnte man noch Destrukturierung und Proxy (in @Rolf B s Benutzernamensraum) verlinken.
Ich frag euch heut abend mal am Stammtisch aus!
Herzliche Grüße
Matthias Scharwies
Guten Morgen!
- JavaScript/Tutorials/OOP/Einstieg
- Infografik (Klasse-Konstruktor-Objektinstanzen) kommt noch
Ich würde evtl. über die Fabrik dann noch einen Prototypen legen.
Herzliche Grüße
Matthias Scharwies
Hallo,
sieht prima aus, Danke!
In der Vorstellung des Konstruktors, fehlt da in der Funktion 'sayname' jeweils das 'this' bei den Namen?
Gruß
Kalk
Servus!
Hallo,
sieht prima aus, Danke!
In der Vorstellung des Konstruktors, fehlt da in der Funktion 'sayname' jeweils das 'this' bei den Namen?
OOPs - danke!
Herzliche Grüße
Matthias Scharwies
Lieber Matthias,
Ich habe jetzt einmal eine überarbeitete Version veröffentlicht: JavaScript/Tutorials/OOP
mir gefällt die Ausführlichkeit. Da ich mit keinem echten Anfänger beide Vorlagen anschauen und ausprobieren konnte, kann ich nicht sicher beurteilen, welche Ausführlichkeit an welcher Stelle welches Verständnis erleichtert. Mir fehlt es zur Zeit schlicht an geeigneten Lerngruppen, um das zu evaluieren.
- JavaScript/Tutorials/OOP/Klassen und Vererbung
- integriert Felix Kapitel mit @Wiko s Änderungen und der prototypischen Vererbung
- zuerst ES6, dann die prototypische V. aus ES3
Mir fällt da etwas im Kapitel 1.2.2 Methoden für Events auf, das ich hier zur Diskussion stellen möchte.
hit (event) {
var classThis = this.self;
return "Ich bin " + classThis._alter + " Jahre alt."
}
Hier soll offensichtlich ein Event verarbeitet werden. Soweit klar. Was mich stört, ist die Annahme, dass man diese Objektmethode zwingend so verwendet:
object.addEventListener("click",p.click);
Diese Einbindung hat tatsächlich das Problem, dass ich innerhalb der Objektmethode hit(event)
ein Problem mit dem Schlüsselwort this
habe. Meiner Meinung nach ist aber die beste Lösung eben nicht, in hit(event)
mit this.self
zu hantieren, sondern die Einbindung so vorzunehmen, dass es das überhaupt nicht erst braucht:
class Person {
constructor (name, alter) {...}
hit (event) { return "Ich bin " + this._alter + " Jahre alt."; }
}
var p = new Person("Frizzy", 15);
var object = document.getElementById("alter");
object.addEventListener("click", event => p.hit(event));
In altmodischerer Schreibweise wäre die letzte Zeile eher so:
object.addEventListener("click", function (event) { p.hit(event); });
Damit ist der this
-Kontext in der Objektmethode von Person
genau der, den man dort gerne haben möchte. Und das Kapitel "Methoden für Events" sollte eher "Umgang mit dem this
-Kontext bei Verwendung von Events" lauten.
Inwiefern man in einer Objektmethode this.self
verwenden kann und wann man so etwas wirklich benötigt, ist eine andere Frage, die meiner Meinung nach an dieser Stelle das Anfängertutorial eher überfrachtet, als das Verständnis (wir sind inhaltlich noch immer ziemlich am Anfang!) zu stärken.
Was meint ihr dazu?
Liebe Grüße
Felix Riesterer
@@Felix Riesterer
Mir fällt da etwas im Kapitel 1.2.2 Methoden für Events auf, das ich hier zur Diskussion stellen möchte.
hit (event) { var classThis = this.self; return "Ich bin " + classThis._alter + " Jahre alt." }
Da fällt mir noch was auf.
Die umständliche, unübersichtliche Schreibweise mit String zusammenbasteln sollte nicht mehr verwendet werden, sondern ein template literal:
return `Ich bin ${classThis._alter} Jahre alt.`;
„Aber der IE!“ – „Shut up!“
Noch besser: mit nicht umbrechendem Leerzeichen zwischen Zahl und Einheit:
return `Ich bin ${classThis._alter}\u{A0}Jahre alt.`;
😷 LLAP
PS: Wer hat da code { overflow: scroll-x }
ins Forum-Stylesheet eingebaut? Das sieht ja furchtbar aus.
Hallo Gunnar,
return `Ich bin ${classThis._alter} Jahre alt.`;
„Aber der IE!“ – „Shut up!“
😀
Noch besser: mit nicht umbrechendem Leerzeichen zwischen Zahl und Einheit:
return `Ich bin ${classThis._alter}\u{A0}Jahre alt.`;
Schöner is' das. Vor allem dann, wenn für die Einheit nur das Einheitenzeichen notiert wird. Hier, wo die Einheit als ganzes Wort ausgeschrieben ist, würde ich auch einen Umbruch verschmerzen.
May the Schwartz be with you
Martin
@@Der Martin
Noch besser: mit nicht umbrechendem Leerzeichen zwischen Zahl und Einheit:
return `Ich bin ${classThis._alter}\u{A0}Jahre alt.`;
Schöner is' das. Vor allem dann, wenn für die Einheit nur das Einheitenzeichen notiert wird.
In dem Falle wäre ein schmales nicht umbrechendes Leerzeichen angebracht:
return `Ich bin ${classThis._gewicht}\u{202F}kg schwer.`;
Siehe Codepen: Hobbits (gezeigt in diesen Vortrag)
😷 LLAP
PS: Mir ist der Unterschied zwischen Masse und Gewicht bewusst. Ich wollte es hier nicht zu schwer machen. (No pun intended.)
Hallo Gunnar,
In dem Falle wäre ein schmales nicht umbrechendes Leerzeichen angebracht:
gibt es inzwischen Browser, die das auch schmal anzeigen?
Gruß
Jürgen
@@JürgenB
gibt es inzwischen Browser, die das auch schmal anzeigen?
Öhm, ja:
Siehe Codepen: Hobbits
Und das Problem sind wohl nicht Browser, sondern dass die verwendeten Fonts auch tatsächlich eine Glyphe für U+202F bereitstellen – und zwar eine mit anderer Breite als für U+0020/U+00A0.
😷 LLAP
Hallo Gunnar,
gibt es inzwischen Browser, die das auch schmal anzeigen?
Öhm, ja:
Siehe Codepen: Hobbits
Und das Problem sind wohl nicht Browser, sondern dass die verwendeten Fonts auch tatsächlich eine Glyphe für U+202F bereitstellen – und zwar eine mit anderer Breite als für U+0020/U+00A0.
betrachtet im iPhone und am W10-PC mit dem FF 78.10.0esr und mit dem Chrome 96: ich sehe keinen Unterschied 😟.
Gruß
Jürgen
@@JürgenB
betrachtet im iPhone und am W10-PC mit dem FF 78.10.0esr und mit dem Chrome 96: ich sehe keinen Unterschied 😟.
Mir dämmert’s: Ich hatte den Codepen ja erstellt, um ihn bei besagtem Vortrag zu zeigen. Als Schrift verwende ich Fira Sans, die habe ich auch lokal installiert. Du vermutlich nicht, deshalb wird’s bei dir in einer anderen Schriftart gerendert, wo womöglich kein Unterschied zwischen normalbreitem und schmalem Leerzeichen ist.
Bei mir sieht’s (bei entsprechender Viewportbreite) so aus:
Muss wohl nochmal nachlesen, wie man Webfonts in CodePen nutzen kann.
😷 LLAP
@@Gunnar Bittersmann
Als Schrift verwende ich Fira Sans, die habe ich auch lokal installiert. Du vermutlich nicht, deshalb wird’s bei dir in einer anderen Schriftart gerendert, wo womöglich kein Unterschied zwischen normalbreitem und schmalem Leerzeichen ist. […]
Muss wohl nochmal nachlesen, wie man Webfonts in CodePen nutzen kann.
Wird der Pen jetzt auch bei euch in Fira Sans gesetzt?
😷 LLAP
Hallo Gunnar,
auf meinem iPhone sind die schmalen Leerzeichen jetzt schmal.
Gruß
Jürgen
Hallo Gunnar,
... Fira Sans ...?
ich habe mir gerade die Tabelle zum Sortierer im Wiki angesehen. Die Seite ist in Helvetica gesetzt, und in meinem Safari werden die Tausendertrenner schmal angezeigt.
Gruß
Jürgen
Hallo Felix,
Was meint ihr dazu?
(1) Sowohl Wiki als auch Du sind im Irrtum mit der Aussage, dass das this-Objekt in diesem Fall das Eventobjekt ist. Das Eventobjekt wird grundsätzlich als Parameter übergeben. Der Wert von this
hängt von der Art der Registrierung ab.
Das ist in einer unheiligen Allianz von DOM und WebIDL Spec exakt festgelegt. Die WebIDL Spec hat einen Abschnitt "Call a user object's operation", die den Umgang mit einem Callback festlegt, und in der DOM Spec steht, dass beim Aufruf eines Eventlisteners für das registrierte Eventlistener-Objekt "call a user object's operation" mit der Operation "handleEvent", Argument "event-Objekt" und thisArg "currentTarget" auszuführen sei. Und in der WebIDL Spec steht dann, dass das Objekt entweder "Callable" sein kann oder ein Objekt mit einer Eigenschaft, die dem Operationsnamen entspricht. Im zweiten Fall wird thisArg durch das EventListener-Objekt ersetzt (WEBIDL 3.11, call a user object's operation, Step 10).
Demnach: Registriert man eine Funktion, enthält this den Wert von event.currentTarget (identisch mit dem Objekt, auf dem der Listener registriert wurde). Registriert man ein EventListener-Objekt, enthält this dieses Objekt.
Das ist auch sinnvoll, denn andernfalls käme man in der handleEvent-Methode nicht an die übrigen Eigenschaften des EventListener-Objekts heran.
Ich habe das vor ein paar Tagen auch hier notiert.
Was mich stört
Mich auch. Und dazu stört mich so einiges mehr.
(1) Anerkannte Application Patterns werden ignoriert
(2) Verletzung von SRP (Single Responsibility Principle).
this
und Behandeln des Click-Events. Das ist falsch.(3) Schlechte Namensgebung. Wieso heißt eine Methode, die das Alter anzeigt, "hit", und nicht "zeigeAlter"?
(4) Ich würde gerne eine Klarstellung haben - außerhalb des Wikis - ob ein EventListener Objekt noch Stand der Technik ist. Dieses Interface findet sich bereits im DOM Level 2 von 2003. Seitdem wurde die bind-Methode (ECMAScript 5.1, 2011) und Pfeilfunktionen (ECMAScript 2015) eingeführt, die das Problem ebenfalls lösen können und es - meine ich - eleganter tun.
MDN schreibt:
Note: Due to the need for compatibility with legacy content, EventListener accepts both a function and an object with a handleEvent() property function.
Angesichts der obigen Zeitleiste ist das Objekt mit handleEvent() Property die Legacy, nicht die Funktion. Wollen wir etwas promoten, das zwecks "compatibility with legacy content" existiert?
Die Pfeilfunktion wurde bereits von Felix gezeigt. Mit bind sähe es so aus:
object.addEventListener("click", p.zeigeAlter.bind(p));
und natürlich gibt's auch die gute alte function-Expression als Fallback.
Bind statt Pfeilfunktion hat eine Existenzberechtigung für Seiten, die Altbrowser unterstützen wollen/müssen. In Browsern, die bind nicht unterstützen, sollte man sich JavaScript besser nicht antun…
Aus meiner Sicht ist ein eventListener-Objekt dann und nur dann sinnvoll, wenn man ein bestimmtes Event unabhängig von einem Modellobjekt behandeln will, und eine Funktion dafür nicht ausreicht. Dafür kann es viele Anlässe geben. Aber zur reinen Delegation eines Events an eine Objektmethode ist es der falsche Ansatz, weil es dafür mittlerweile standardisierte Möglichkeiten gibt.
Rolf
Hallo Rolf,
Überarbeitet: https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/OOP/Objekte_und_ihre_Eigenschaften#this
Rolf
Hallo Rolf,
Konstruktoren überarbeitet, Abschnitt über Prototypen hinzugefügt.
Da stand einiges, was falsch war. Dass Prototypen ein Bauplan sind und das Instanzobjekt eine Kopie des Prototypen - nein. Definitiv nein. Die Bauplanmetapher gilt für Klassen der OOP, aber nicht für Prototypen.
Die Umleitung für [[Prototyp]] und [[Prototype]] könnte nun auf das Prototyp-Kapitel dieses Artikels zeigen. Die aktuelle Zielposition ist ja ohnehin auf der Kippe.
Rolf
Hallo,
Mir fällt da etwas im Kapitel 1.2.2 Methoden für Events auf, das ich hier zur Diskussion stellen möchte.
ich muss zu meiner Schande gestehen, das ich in diesem Unterkapitel zwar das this-Problem, sonst aber nichts verstanden habe.
Was macht
this.click = {handleEvent:this.hit, self:this};
und warum wird die Methode click
im constructor definiert?
Wer bearbeitet den return-Wert von hit
?
Gruß
Jürgen
Lieber JürgenB,
ich muss zu meiner Schande gestehen, das ich in diesem Unterkapitel zwar das this-Problem, sonst aber nichts verstanden habe.
Was macht
this.click = {handleEvent:this.hit, self:this};
und warum wird die Methode
click
im constructor definiert?
das ist mir auch sehr schleierhaft. In meinen Projekten hätte ich die Methode hit
so gestaltet, dass sie wie jede andere Methode der Klasse auch von einem this
ausgehen kann, welches auf die Objektinstanz zeigt. Um das zu erreichen verwende ich addEventListener
entsprechend:
node.addEventListener("click", event => myObject.myMethod(event));
Wer bearbeitet den return-Wert von
hit
?
Der landet im digitalen Nirvana. Offensichtlich ist die Überarbeitung noch in vollem Gange, sodass wir beide einfach abwarten sollten, bis eine endgültige (oder "Meilenstein"-) Fassung erreicht ist. Dann wird uns das Beispiel sicher sofort einleuchten.
Liebe Grüße
Felix Riesterer
Hallo Felix,
ich beschäftige mich gerade mit Pointerevents, und da mit vielen Pointern. Um mit den diversen Eventhandlern und dem Eventcache nicht zu viele globale Objekte zu haben, habe ich alles in einer Klasse gebündelt. Das this-Problem habe ich erst mal mit der Pfeilfunktion gelöst.
Meiner Meinung nach gehören in dieses Tutorial aber auch noch Setter und Getter.
Gruß
Jürgen
Servus!
Hallo Felix,
ich beschäftige mich gerade mit Pointerevents, und da mit vielen Pointern. Um mit den diversen Eventhandlern und dem Eventcache nicht zu viele globale Objekte zu haben, habe ich alles in einer Klasse gebündelt. Das this-Problem habe ich erst mal mit der Pfeilfunktion gelöst.
Meiner Meinung nach gehören in dieses Tutorial aber auch noch Setter und Getter.
Ja, @Rolf B hat(te) die schon in seinem Entwurf drin:
Herzliche Grüße
Matthias Scharwies
Hallo JürgenB,
Was macht
this.click = {handleEvent:this.hit, self:this};
und warum wird die Methode click im constructor definiert?
Da wird keine Methode definiert. Da wird ein Objekt erzeugt, das die EventListener-Schnittstelle implementiert. Das ist Technik von anno Tobak, wie ich hier schon schrub und die Relevanz befragte. Warum "Methoden für Events" in dem Kapitel stehen, ist ohnehin fragwürdig, diese Diskussion gehört generell zu Methoden und this
.
Einerseits habe ich das [hier](und warum wird die Methode click im constructor definiert?) angerissen, das kann man ggf. noch vertiefen, und andererseits kann man das im Zusammenhang mit addEventListener nochmal ausführen.
Dieses Objekt kann dann von einem Nutzer des Objekts verwendet werden, um ein click-Event von diesem Objekt behandeln zu lassen. Was ich in der gezeigten Form architektonisch missbillige und im oben verlinkten Beitrag ebenfalls schreibte.
Im übrigen verhält sich der Ablauf fast genauso, als ob man eine Funktion als Event Listener verwenden würde, d.h. was mit dem Rückgabewert gemacht wird, steht nicht in der Spec. Aber traditionell, aus Zeiten vor DOM Level 2, wird return false wie event.preventDefault() behandelt. Meine ich...
Es ist fast genauso, weil das this
unterschiedlich ist. Ein Funktions-Eventlistener bekommt event.currentTarget als this und ein Objekt-Eventlistener bekommt das Objekt als this.
Quelle: DOM Spec, inner invoke Schritt 10, und dann WebIDL Spec, Schritt 9 und 10.
Rolf
Hallo Rolf,
ich habe mal etwas recherchiert und diese Lösung gefällt mir am besten:
class Pointerevents {
constructor(pointertarget) {
pointertarget.addEventListener("pointerdown", this.down , false);
...
}
down = (event) => this.handledown(event);
handledown(event) {
const id = event.pointerId;
event.preventDefault();
this.pointereventcache[id] = event;
...
} // down
...
}
new Pointerevents(document.body);
Bei dieser Variante können die Eventhandler auch wieder entfernt werden.
Gruß
Jürgen
Lieber JürgenB,
pointertarget.addEventListener("pointerdown", this.down , false); ... down = (event) => this.handledown(event); handledown(event) { ... }
da bin ich mir nicht sicher, ob die "lokale Funktion" (oder "nur" eine Closure?) namens down
in dieser Klassensyntax nicht einen Fehler wirft. Meiner Erinnerung nach ist innerhalb der Klassensyntax ein implizites "use strict" enthalten, welches vor down
ein let|const|var erfordert.
Warum nicht gleich so?
pointertarget.addEventListener(
"pointerdown",
event => this.handledown(event),
false
);
Liebe Grüße
Felix Riesterer
Hallo Felix,
Lieber JürgenB,
pointertarget.addEventListener("pointerdown", this.down , false); ... down = (event) => this.handledown(event); handledown(event) { ... }
da bin ich mir nicht sicher, ob die "lokale Funktion" (oder "nur" eine Closure?) namens
down
in dieser Klassensyntax nicht einen Fehler wirft. Meiner Erinnerung nach ist innerhalb der Klassensyntax ein implizites "use strict" enthalten, welches vordown
ein let|const|var erfordert.
das ist so im Einsatz. Ein let|const|var vor dem down würde einen Fehler werfen. Variablen dürfen in Klassen nur innerhalb von Methoden deklariert werden.
Warum nicht gleich so?
pointertarget.addEventListener( "pointerdown", event => this.handledown(event), false );
so kann man den Eventhandler nicht entfernen. Und ob der Handler innerhalb der Klasse oder außerhalb registriert wird, hängt von der Anwendung ab bzw. ist Geschmacksache.
Gruß
Jürgen
Hallo JürgenB,
Und ob der Handler innerhalb der Klasse oder außerhalb gegistriert wird, hängt von der Anwendung ab bzw. ist Geschmacksache.
Ob nun re- oder gegistriert, Geschmackssache sollte das nur ausnahmsweise sein. Die SOLID Prinzipien dürften in den meisten Fällen klare Richtlinien liefern, wo eine Eventregistrierung hingehört und wo nicht.
Rolf
Hallo Rolf,
Ob nun re- oder gegistriert,
grrrrr. Hab das mal korrigiert.
Geschmackssache sollte das nur ausnahmsweise sein. Die SOLID Prinzipien dürften in den meisten Fällen klare Richtlinien liefern, wo eine Eventregistrierung hingehört und wo nicht.
OK
Gruß
Jürgen
Hallo Felix,
nein, das funktioniert. Das ist die korrekte Syntax zum Definieren von Instanzproperties. Mit static davor wäre es ein Klassenproperty.
Die Syntax ist allerdings neu. Brandneu. Kangax listet es als ES2022 Feature, das seit Ende 2020 ziemlich breit unterstützt wird, mit Nachzügler Firefox (ab v90).
Man kann das also mittlerweile empfehlen.
Rolf
Hallo Rolf,
Die Syntax ist allerdings neu. Brandneu. Kangax listet es als ES2022 Feature, das seit Ende 2020 ziemlich breit unterstützt wird, mit Nachzügler Firefox (ab v90).
der 78.10.0.esr auf meinem Dienstrechner unterstützt es auch schon.
Gruß
Jürgen
Hallo JürgenB,
78.10.0.esr
stimmt, habe nicht gesehen dass Kangax die FF vor 90 als "partiell" auflistet und die Partialität sich darauf bezieht, dass nur die private instance properties fehlen. FF78 ist laut en-Wikipedia von Mitte '20, also on par mit den anderen Browsern.
Rolf
Hallo Matthias,
ich stolpere nochmal über die Unterobjekte.
Ich weiß, dass man hier an einem sehr frühen Punkt ist, aber trotzdem müsste man eigentlich zwischen abhängigen und unabhängigen Objektbeziehungen unterscheiden. Um beim Beispiel zu bleiben: Ein Baby ist - vor der Geburt - von seiner Mutter abhängig - kommt der erwähnte Bus, sind beide tot. Die Mutter könnte aber auch ein Objekt "Handtasche" haben, mit Inhalten wie Ausweis, Autoschlüssel und Pfefferspray. Besagter Bus kann die Mutter töten, aber die Handtasche existiert als Objekt weiter. In beiden Fällen liegt eine Assoziation vor, aber das Baby ist vom Typ Komposition ("Y is-part-of X") und die Handtasche vom Typ Aggregation ("X has-a Y"). Das Baby ist deshalb auch ein interessantes Beispiel, denn ab einem gewissen Moment wechselt es seine Assoziationsart von part-of zu has-a.
So richtig problematisch ist an dieser Stelle der Scope. Objektbeziehungen erschaffen keinen Scope - das passiert beim Schachteln von Funktionen. Eine Funktion Y, die innerhalb einer Funktion X definiert wird, kann auf die Daten von X zugreifen (was eine grobe Vereinfachung darstellt, mit Details schmeißt das Wiki beim Them Closures um sich). Bei Eltern- und Kindobjekt dagegen kommt es darauf an, welche Verknüpfung erzeugt worden ist. Wenn die Mutter ein Property "baby" enthält, kann die Mutter auf das Kindobjekt zugreifen. Das Kind kann damit existieren, ohne etwas von der Mutter zu wissen. Wenn das Kindobjekt ein Property "mother" bekommt, kann es auch auf seine Mutter zugreifen. Das ist was ganz anderes.
Eine gute Formulierung für den Abschnitt habe ich noch nicht; ich muss jetzt erstmal weg und denke später nochmal drüber nach.
Rolf
Hallo Rolf,
ich würde den ganzen Abschnitt am liebsten durch dies hier ersetzen, bin damit aber noch nicht ganz zufrieden.
Rolf
Servus!
- JavaScript/Tutorials/OOP/Objekte und ihre Eigenschaften
- kontextualisiert mit Personen
- Live-Beispiele (um Änderungen gleich in der Konsole zu sehen)
- Passen Kind-Objekte in den Aufbau oder sollte man sie streichen / woanders einsetzen?
ich würde den ganzen Abschnitt am liebsten durch dies hier ersetzen, bin damit aber noch nicht ganz zufrieden.
Für mich sieht's gut aus. Die (evtl. doppelt vorhandenen) Adressen sind auch eine gute Idee.
Ich weiß aber nicht, wie viel ins erste Praxis-Kapitel passt (jetzt sind noch Prototypen dabei).
Evtl. sollten wir es eben auf mehrere, thematisch getrennte Kapitel aufteilen. Nicht alles muss im ersten Kapitel in der ersten Stunde behandelt werden.
Herzliche Grüße
Matthias Scharwies
Hallo Matthias,
ja, guter Plan. Eigenschaften und Methoden in Objekten ohne Konstruktoren, dann Konstruktoren und Prototypen, dann Objektbeziehungen. Das sind 3 nicht zu lange Artikel, und man kann sie ggf. ausbauen.
Ich würde DANN aber bei Objekte und Eigenschaften noch einen Abschnitt anfügen wollen, als "optionale Lektüre", der auf defineProperty eingeht, womit man readonly-Properties sowie getter und setter erzeugen kann.
Rolf
Hallo Rolf,
Ich würde DANN aber bei Objekte und Eigenschaften noch einen Abschnitt anfügen wollen, als "optionale Lektüre", der auf defineProperty eingeht, womit man readonly-Properties sowie getter und setter erzeugen kann.
ich bin ja froh, dass du das als optionale Lektüre einordnest. Denn ich halte mich selbst nicht für ganz ahnungslos in Javascript (also nicht Fußgänger, mindestens schon Radfahrer), aber das ist dann auch für mich schon relativ schwere Kost.
May the Schwartz be with you
Martin
Hallo Matthias,
ich hatte jetzt drei Stunden lang im Objekte+Eigenschaften Artikel etliche Änderungen vorgenommen, ohne zwischenzuspeichern. Kann man ja nicht, ohne zu veröffentlichen. Und jedesmal einen Artikel in den Userspace zu legen ist lästig. Dem Wiki fehlt eine "Autosave Draft" Funktion, wie im Forum.
Denn: wie es mir REGELMÄSSIG irgendwann passiert - ich bin irrtümlich auf Strg+W gekommen und das Browsertab geht ohne Rückfrage zu. Beim Close eines Tab fragt er ja wenigstens rück, aber Strg+W ist der ultimative Boss-Key. Der Idiot, der das festgelegt hat, gehört einen Kopf kürzer gemacht, und zwar an den Füßen, damit er was davon hat! Diese Taste ist viel zu schnell irrtümlich erwischt.
Für Chrome habe ich jetzt den Tipp gefunden, nach chrome://extensions zu gehen und die Tastenkombination einer Extension zuzuweisen, die nicht relevantes tut. Bei mir ist es der Google Drive Anwendungslauncher. Und Strg+W ist wirklungslos. Endlich.
Oh! Nachtrag: Strg+Shift+T - reopen closed tab. Klappt auch mehrfach, und hat mich gerettet. Hatte ich vorhin probiert, aber per Maus im Menü, und nur den Stand VOR meiner Bearbeitung gefunden.
D.h. mein Text ist wieder da, und steht auf meiner Benutzerseite unter Benutzer:Rolf B/Objekte.
Was ich eigentlich wissen wollte: welche Herkunft hat der aktuelle Text eigentlich? Ist das von Wiko, und wenn ich darin grob ändere, fange ich mir Ärger ein? Oder ist es alter Molily Text und Freiwild?
Rolf
Lieber Rolf!
D.h. mein Text ist wieder da, und steht auf meiner Benutzerseite unter Benutzer:Rolf B/Objekte.
Der sieht gut aus, …
Was ich eigentlich wissen wollte: welche Herkunft hat der aktuelle Text eigentlich? Ist das von Wiko, und wenn ich darin grob ändere, fange ich mir Ärger ein? Oder ist es alter Molily Text und Freiwild?
Das ist, wie ich oben oben geschrieben hatte, von mir.
Ich hatte im März/Mai 2016 ja schon einmal angefangen, den Molily-Text durch eine eigene Variante zu ersetzen. Damals hatten parallel @Orlok JavaScript/Objekte/Object und Du Benutzer:Rolf_b/tempObjekteEigenschaften entwickelt, in den ich immer wieder reinschaue.
In der Neufassung vom August 2020, die ich nur im Test-Wiki angefangen hatte und die durch Felix' OOP-Tutorial im Feb 2021 dort erst mal liegengeblieben war, wollte ich zeigen, wie man mit der Konsole eben gleich untersuchen kann, wie Objekte aufgebaut sind. Das habe ich in einem Tutorial / Blog-Post bei Dillion Megida gesehen, das ich auch als Fußnote verlinkt habe.
Ich hatte versucht den Spagat zu schaffen. Objekte richtig zu erklären und das Unnötige wegzulassen, bzw Grundlagen, die bereits in den Anfänger-Tutorials stehen, passend zu verlinken.
Was ich nicht in ein Fortgeschrittenen-Tutorial einbauen würde, wäre die Diskussion const oder let, die ich als Fußnote erwähnt habe, sowie die Arbeit mit der Konsole / Console, die ja im Kurs Einstieg in JavaScript erklärt wird. [1]
Wiko hat Felix' Klassen_und_Vererbung überarbeitet und durch Methoden_für_Events erweitert. Er möchte dort auch weitermachen.
Was mir am ganzen Kurs noch fehlt, ist neben den Erklärungen ein Projekt, das man zusammen mit dem Leser entwickelt. Da hatte ich seit 2016 eben einen Vokabeltrainer im Auge, dessen JSON-Struktur dann auch erklärt worden wäre. So hätte man einen roten Faden und wäre nicht versucht, alle Alternativen in den Text zu integrieren.
Da jetzt die molily-Texte im Kurs integriert sind, um Dopplungen zu vermeiden, werde ich (aber erst zum Jahreswechsel) ein Autorennen programmieren.
Früher ging sowas mit Benzin, heute wohl eher mit Akku und Super-Charger. Im Netz geht alles mit canvas; evtl. kann man wenigstens die Autos und den Hintergrund mit SVG bauen.
function Auto(startpos, benzin, startgeschwindigkeit)
{
this.s = startpos;
this.benzin = benzin;
this.v = startgeschwindigkeit;
}
Herzliche Grüße
Matthias Scharwies
Dieses Tutorial ist oben in der {{Vorlage:Text-Info}} als vorausgesetztes Wissen verlinkt. Der Link auf [[Seiteninspektor]] im Text führt auf Grundlagen/Webprojekte/testen, wo der Seiteninspektor erst im 3. Absatz und da nur für HTML erklärt wird. Das könnte/sollte man ändern. ↩︎
@@Rolf B
Denn: wie es mir REGELMÄSSIG irgendwann passiert - ich bin irrtümlich auf Strg+W gekommen und das Browsertab geht ohne Rückfrage zu.
Passiert mir auch desöfteren. Bei mir ist [alt][shift][W] die Tastenkombination fürs öffnende Anführungszeichen „. Wenn ich statt [alt] das daneben liegende [cmd] erwische, ist nicht nur das Browsertab weg ([cmd][W]), sondern wegen [shift] gleich das ganze Browserfenster. 🤬
😷 LLAP
Moin,
Denn: wie es mir REGELMÄSSIG irgendwann passiert - ich bin irrtümlich auf Strg+W gekommen und das Browsertab geht ohne Rückfrage zu. Beim Close eines Tab fragt er ja wenigstens rück, aber Strg+W ist der ultimative Boss-Key. Der Idiot, der das festgelegt hat, gehört einen Kopf kürzer gemacht, und zwar an den Füßen, damit er was davon hat! Diese Taste ist viel zu schnell irrtümlich erwischt.
wenn du den gefunden hast, sag Bescheid! Dann sammle ich ein paar Kilo Katzendreck.
Ehrlich, so eine dämliche Idee! Dafür gibt's doch seit ewigen Zeiten schon Ctrl-F4.
May the Schwartz be with you
Martin