Tutorials für JavaScript Patterns gesucht
MB
- javascript
0 Mitleser3 Orlok0 Felix Riesterer
nabend Community,
wo finde ich hier ein Tutorial für JS Patterns?
Ich hab mal unteranderem auf YouTube gesucht und gefunden. Das ist leider auf Englisch und beinhaltet viele neue Funktionen z.B. prototype oder call. Diese sind glaube ich in der aktuellen JS Version Aufgelistet und gabs früher noch nicht.
Tutorials auf YouTube sind meines erachtens für den kleinen Einstieg gut wenn man der Englichen Sprache und den akzenten mächtig ist was ich nicht bin.
LG MB
Hallo MB
Ich hab mal unter anderem auf YouTube gesucht und gefunden. Das ist leider auf Englisch und beinhaltet viele neue Funktionen z.B. prototype oder call. Diese sind glaube ich in der aktuellen JS Version aufgelistet und gabs früher noch nicht.
Weder prototype
noch call
sind in irgendeiner Form neu, und bei prototype
handelt es sich zumindest auf Sprachebene auch nicht um eine Funktion, jedenfalls in der Regel nicht. Eine Ausnahme von der Regel ist allerdings Function.prototype
, dessen eigene Methode call
ist. Aber das ist in diesem Zusammenhang kaum relevant.
Die Eigenschaft prototype
von Funktionsobjekten dient der Implementierung prototypischer Vererbung und ihr Wert ist üblicherweise ein gewöhnliches Objekt; Wird eine Funktion als Konstruktor aufgerufen, also entweder durch den Operator new
oder unter Verwendung der Methode Reflect.construct
, dann wird von der Funktion automatisch ein neues gewöhnliches Objekt erzeugt und zurückgegeben.
Dieses erzeugte Objekt wiederum hat eine Verbindung zu der Eigenschaft prototype
des Konstruktors, das heißt, der Prototyp des erzeugten Objektes ist der Wert dieser Eigenschaft. Ist nun, wie dies standardmäßig der Fall ist, als Wert der Eigenschaft prototype
ein Objekt hinterlegt, dann können dessen Eigenschaften und Methoden auch über das neu erzeugte Instanzobjekt referenziert werden; Sie werden also an dieses Objekt vererbt.
Sehen wir uns das Ganze aber mal an einem Beispiel etwas genauer an, wobei wir zunächst eine Funktion definieren, die wir dann später als Konstruktor aufrufen werden; Weil abgesehen von Pfeilfunktionen prinzipiell alle selbstdefinierten Funktionen als Konstruktor verwendet werden können, spielt die Art der Definition dabei keine Rolle.
Das heißt, es ist unerheblich, ob die Funktion wie im folgenden Beispiel deklariert wird, oder ob sie als Ausdruck notiert und das Funktionsobjekt einer Variable, Konstante oder Objekteigenschaft als Wert zugewiesen wird. Zu beachten ist hier ersteinmal nur die allgemeine Konvention, den ersten Buchstaben des Funktionsbezeichners groß zu schreiben, wodurch die Absicht zum Ausdruck gebracht wird, diese Funktion als Konstruktor zu verwenden.
function Constructor ( ) {
'use strict';
this.property = 'value';
}
Wird eine Funktion als Konstruktor aufgerufen, dann wird wie gesehen ein neues Objekt erzeugt. Dieses Objekt kann innerhalb des Funktionskörpers über die Kontextvariable this
angesprochen werden, sprich, die Funktion wird beim Aufruf als Konstruktor im Kontext des Instanzobjektes ausgeführt.
Entsprechend können wie in dem Beispiel oben bereits bei der Ausführung des Konstruktors eigene Eigenschaften und Methoden auf dem erzeugten Objekt definiert werden. Hier also eine Eigenschaft mit dem Namen property
, welcher der der Wert 'value'
zugewiesen wird. Jede von diesem Konstruktor erzeugte Instanz besitzt demnach also selbst eine solche Eigenschaft.
Zu beachten ist hier darüber hinaus die Anweisung 'use strict'
, die dafür sorgt, dass die Funktion Constructor
im Strict Mode ausgeführt wird. Dies ist eine Vorsichtsmaßnahme um zu verhindern, dass versehentlich globale Variablen erzeugt werden, wenn die Funktion nicht als Konstruktor aufgerufen wird.
Denn im normalen Ausführungsmodus verweist this
bei einem gewöhnlichen Funktionsaufruf auf das globale Objekt, also üblicherweise window
, dessen Eigenschaften in der Regel gleichzeitig globale Variablen sind. Würde Constructor
also im normalen Ausführungsmodus aufgerufen und dabei das Schlüsselwort new
vergessen werden, dann würde eine neue globale Variable mit dem Bezeichner property
angelegt.
Im Strict Mode ist der Wert von this
bei einem normalen Funktionsaufruf hingegen nicht window
, sondern der primitive Wert undefined
. Das heißt, in dem Fall, dass beim Aufruf das Schlüsselwort new
vergessen wird, würde keine globale Variable angelegt, sondern die Zuweisung würde einen Fehler produzieren.
function Constructor ( ) {
if (!new.target) {
throw new TypeError('Constructor called without new');
}
this.property = 'value';
}
Zu diesem Zweck könnte man übrigens auch den Operator new.target
verwenden, der im Falle des Aufrufs als Konstruktor auf die aufgerufene Funktion verweist, hier also Constructor
, sonst jedoch den Wert undefined
zurückgibt. Hierbei handelt es sich allerdings in der Tat um ein relativ neues Feature, dass gegebenenfalls noch nicht von allen relevanten Ausführungsumgebungen unterstützt wird.
console.log(typeof Constructor.prototype); // object
Jedenfalls besitzt unser Konstruktor wie alle gewöhnlichen Funktionen eine Eigenschaft mit dem Namen prototype
, in der ein planes Objekt hinterlegt ist. Dieses Objekt besitzt standardmäßig nur eine eigene Eigenschaft, nämlich die Eigenschaft constructor
, welche eine Referenz auf das dazugehörige Funktionsobjekt enthält, hier also auf unsere Funktion Constructor
.
const value = Constructor.prototype.constructor;
console.log(value === Constructor); // true
Nun definieren wir auf dem Objekt, welches in der Eigenschaft Constructor.prototype
hinterlegt ist eine Methode, welche die Anweisung beinhaltet, den Wert der Eigenschaft property
des Objektes zurückzugeben, in dessen Kontext die Methode ausgeführt wird.
Constructor.prototype.method = function ( ) {
return this.property;
};
Dabei ist zu berücksichtigen, dass die Kontextvariable this
im Falle eines Methodenaufrufs immer auf das Objekt zeigt, auf dem die Funktion aufgerufen wurde. Das heißt, wenn der Aufruf über einen Elementausdruck nach dem Schema object.method()
erfolgt, dann ist der Wert von this
innerhalb der Funktion immer das Objekt, über das die Funktion beim Aufruf referenziert wurde.
const instance = new Constructor;
console.log(typeof instance); // object
Nachdem wir nun also eine Konstruktorfunktion erstellt haben und auf dem Objekt, welches in der Eigenschaft prototype
hinterlegt ist, eine Methode definiert haben, rufen wir die Funktion jetzt mittels des Operators new
als Konstruktor auf, sodass ein neues Objekt erzeugt und zurückgegeben wird, das in der Konstante mit dem Bezeichner instance
gespeichert wird.
Da der Aufruf von Constructor
durch den Operator new
erfolgt und wir hier keine Argumente an die Funktion übergeben, können wir uns die Notierung der runden Klammern nach dem Funktionsbezeichner sparen.
console.log(instance.hasOwnProperty('property')); // true
console.log(instance.property); // value
Unser auf diese Weise erzeugtes Instanzobjekt besitzt nun eine eigene Eigenschaft namens property
deren Wert der String 'value'
ist, da wir im Funktionskörper unseres Konstruktors die entsprechende Zuweisung vorgenommen haben. Aber das ist natürlich nicht alles.
console.log(instance.hasOwnProperty('method')); // false
const value = instance.method( );
console.log(value); // value
Denn wir haben auf dem Objekt Constructor.prototype
ja noch eine Methode mit dem Namen method
definiert. Diese Methode wird nun bei der Erzeugung des Instanzobjektes nicht auf dieses kopiert, weshalb die Überprüfung mittels hasOwnProperty
, ob es sich um eine eigene Eigenschaft handelt, entsprechend das Ergebnis false
ergibt; Aber sie kann dennoch auf der Instanz aufgerufen werden, da Constructor.prototype
der Prototyp dieses Objektes ist.
Das heißt, bei dem Versuch, die Methode method
auf instance
zu referenzieren wird intern zunächst geprüft, ob das Objekt instance
selbst über eine solche Methode verfügt. Was hier nicht der Fall ist. Da die Suche auf diesem Objekt also erfolglos bleibt, wird in einem zweiten Schritt nachgesehen, ob der Prototyp von instance
über eine entsprechende Methode verfügt.
const proto = Object.getPrototypeOf(instance);
console.log(proto === Constructor.prototype); // true
Da der Prototyp von instance
nun das Objekt Constructor.prototype
ist und weil auf diesem Objekt eine Methode mit dem Namen method
definiert ist, wird schließlich diese Methode referenziert und im Kontext des Objektes instance
aufgerufen, sodass im Ergebnis der Wert der Eigenschaft property
von instance
zurückgegeben wird. Die Methode method
wird also von Constructor.prototype
an instance
vererbt.
Nun haben wir in den Beispielen oben darüber hinaus zweimal die Methode hasOwnProperty
auf dem Instanzobjekt aufgerufen, bei der es sich ebenfalls nicht um eine eigene Methode dieses Objektes handelt, sondern um eine Methode, die eigentlich auf dem Objekt Object.prototype
definiert ist.
console.log(Object.prototype.hasOwnProperty('hasOwnProperty')); // true
const proto = Object.getPrototypeOf(Constructor.prototype);
console.log(proto === Object.prototype); // true
Da Object.prototype
jedoch der Prototyp von Constructor.prototype
ist, und weil wie gesehen beim Zugriff auf eine Eigenschaft oder Methode auch die jeweiligen Prototypen durchsucht werden, wird die Methode hasOwnProperty
ebenso wie die Methode method
beim Aufruf auf instance
über die Prototypenkette referenziert.
Der Zweck der Eigenschaft prototype
von Funktionsobjekten ist also, allen von der Funktion erzeugten Objekten Methoden und Eigenschaften zur Verfügung zu stellen, ohne diese auf den Objekten selbst definieren zu müssen.
Darum spricht man hier auch von Differenzieller Vererbung, das heißt, ein Prototyp stellt die Funktionalität zur Verfügung, die bei allen von diesem Prototypen erbenden Objekten vorhanden sein soll, während auf den Instanzobjekten selbst nur die Unterschiede, also die Differenzen definiert werden müssen.
Eine etwas ausführlichere Erklärung zu dem Thema bietet der Artikel Vererbung im Wiki.
Es soll allerdings nicht verschwiegen werden, dass die Erzeugung von Objekten durch den Aufruf einer Funktion oder Klasse mittels new
nicht die einzige Möglichkeit darstellt, prototypische Vererbung zu implementieren.
const proto = {
method ( ) {
return this.property;
}
};
const instance = Object.create(proto);
instance.property = 'value';
console.log(instance.method( )); // value
Zu diesem Zweck kann nämlich auch die Methode Object.create
verwendet werden, welche ein neues planes Objekt erzeugt und als dessen Prototyp das Objekt installiert, welches der Methode als erstes Argument übergeben wurde.
Was nun die Methode call
angeht, ist zu erwähnen, dass diese auf Function.prototype
definiert ist, und da alle Funktionen von Function.prototype
erben, kann sie entsprechend auch auf allen Funktionen aufgerufen werden.
Die Methode call
ermöglicht es, eine Funktion in einem bestimmten Kontext aufzurufen. Das heißt, die Kontextvariable this
der auf diese Weise aufgerufenen Funktion wird mit dem Wert initialisiert, welcher der Methode call
als erstes Argument übergeben wurde.
function getThis (parameter) {
console.log(parameter);
return this;
}
const result = getThis.call('value', 'argument'); // argument
console.log(result); // value
Mit den weiteren an die Methode call
übergebenen Argumenten wird dann die Funktion aufgerufen, auf der die Methode ausgeführt wird, weshalb der Parameter in dem Beispiel oben mit dem String 'argument'
initialisiert wird.
Soll eine Funktion also explizit in einem bestimmten Kontext aufgerufen werden kann dies mit call
bewerkstelligt werden. Oder mit der Methode Function.prototype.apply, welche die Argumente für den Aufruf in Form eines Arrays entgegennimmt.
Gruß,
Orlok
Lieber Orlok,
wo genau können wir diesen Deinen Wiki-Tutorial-Artikel im Wiki einfügen?
Das nächste Mal vielleicht dieses Posting gleich als Wiki-Artikel an entsprechender Stelle veröffentlichen und hier nur noch darauf verlinken? So á la "hab' mal eben schnell einen Artikel veröffentlicht, der sich als Antwort auf Deine Frage eignet" vielleicht?
Wow, so viel Schaffenskraft - und dann isses nur ein Forumsposting... das sollte so nicht bleiben!
Liebe Grüße,
Felix Riesterer.
Hallo Felix
Das nächste Mal vielleicht dieses Posting gleich als Wiki-Artikel an entsprechender Stelle veröffentlichen und hier nur noch darauf verlinken?
Muss ein Déjà-vu sein. Irgendwie habe ich das Gefühl, als hätte ich die Diskussion schonmal geführt.
Jedenfalls, nicht jeder längere Beitrag hätte alternativ auch als Wiki-Artikel verfasst werden können, und ganz bestimmt nicht dieser spezielle Beitrag. Das ist überhaupt so gut wie nie sinnvoll, denn das würde voraussetzen, dass es im Wiki zufällig eine inhaltliche Lücke gibt, welche sich mit der Thematik der zu gebenden Antwort nahezu vollständig deckt.
Meist ist es jedoch so, dass die entsprechenden Informationen durchaus (teilweise) vorhanden sind, aber vielleicht auf mehrere Artikel und Abschnitte verteilt. Oder, wenn die Informationen tatsächlich nicht vorhanden sind, wäre es mit Blick auf die Systematik des Wikis womöglich sinnvoll, diese über mehrere Artikel und Abschnitte zu verteilen, sodass es mit einem einzelnen Artikel im Ergebnis nicht getan wäre.
Darüber hinaus ist das Schreiben einer Antwort hier im Forum kaum mit dem Verfassen eines Artikels für das Wiki zu vergleichen, denn ein Wiki-Artikel erfordert viel gewissenhaftere Arbeit, größeren Bedacht bei jeder Formulierung und überhaupt eine sorgsamere Auswahl der dargestellten Informationen. Das Verfassen eines Wiki-Artikels ist in der Regel also mit ungleich größerem Aufwand verbunden.
Aber hey, was weiß ich schon vom Artikelschreiben für’s Wiki?
Wow, so viel Schaffenskraft - und dann isses nur ein Forumsposting... das sollte so nicht bleiben!
Da hast du allerdings recht. Ich habe tatsächlich schon viele Antworten hier im Forum geschrieben, bei denen ich mir sehr viel Mühe gegeben – und in die ich auch sehr viel Zeit investiert habe. Geholfen habe ich damit aber wohl kaum jemandem; Bloß Kraft und Zeit habe ich verschwendet, die ich anderswo besser hätte einsetzen können. Ich sollte mir solche Antworten in Zukunft also einfach sparen.
Gruß,
Orlok
nabend Orlok,
aaah das mit dem window-Objekt wo this probleme macht. da habe ich, wie mir in SelfHTML empfolen wurde, that = this ausgetauscht. Und das die Variable undefine neu ist war mir auch nicht bewusst. Erst einmal danke für deinen umfangreichen Beitrag.
Ich muss den Text erstmal verdauem bis ich ihn verstehe.
Herzliche Grüße MB
Lieber MB,
wo finde ich hier ein Tutorial für JS Patterns?
was sind "JS Patterns"? Meinst Du vielleicht reguläre Ausdrücke in JS?
Liebe Grüße,
Felix Riesterer.
wo finde ich hier ein Tutorial für JS Patterns? was sind "JS Patterns"? Meinst Du vielleicht [reguläre Ausdrücke]
Wohl eher sowas wie https://addyosmani.com/resources/essentialjsdesignpatterns/book/
das habe ich gerade als ersten Googletreffer gefunden und kann die Verständlichkeit der Darstellung nicht beurteilen...
Hier im Wiki sind die Dinge etwas verteilt, und Orloks Langposting wäre als eigener Beitrag deshalb ein Problem, weil den Artikeln, die es im WIKI gibt, die Systematik fehlt. Der Beitrag an sich ist gut, aber eine Perle von vielen im <übertreibung>JavaScript-Sauhaufen</übertreibung>.
Rolf
Servus!
Hier im Wiki sind die Dinge etwas verteilt, und Orloks Langposting wäre als eigener Beitrag deshalb ein Problem, weil den Artikeln, die es im WIKI gibt, die Systematik fehlt. Der Beitrag an sich ist gut, aber eine Perle von vielen im <übertreibung>JavaScript-Sauhaufen</übertreibung>.
Die anscheinend fehlerhafte oder mangelnde Systematik ist im Laufe der Jahre so gewachsen und war schon öfter Gegenstand von Diskussionen.
JavaScript/grundlegende Konzepte wurde nach dieser Diskussion "JavaScript im Wiki" durch eine Textübertragung der von Mitleser angesprochenen JavaScript-Dokumentation vom molily ersetzt. Ich habe versucht, sie, soweit es mir möglich war, zu aktualisieren. Danke an @Rolf b, dass er den ersten Artikel überarbeitet.
@Orlok hat dankenswerterweise die noch fehlenden Artikel zur Ereignisbehandlung und den Objekten Object und Function mit ihren Eigenschaften und Methoden erstellt.
Ich kann immer wieder nur appellieren:
Meldet Fehler und Inkonsistenzen, indem ihr ein {{ToDo}} einfügt.
Bessert fehlerhafte Angaben eventuell gleich selbst aus.
Macht Vorschläge für eine Umbenennung, Verschiebung und Aufteilung von Seiten.
Mich frustriert einerseits die pauschale Kritik, die m.E. derjenigen von "in der alten 8.12. habe ich alles gefunden" ähnelt und andererseits die fehlende Resonanz im Selfraum, die uns bewussten Schwächen konkret zu beseitigen. Die spärliche Beteiligung an den von der MV vorgeschlagenen Wiki-Pushes ist da der beste Beweis.
Herzliche Grüße
Matthias Scharwies
Hallo Matthias,
ich wollte dich nicht frustrieren. Es ist Wahnsinn, wieviel Arbeit du hier investierst, und leider hat nicht jeder die Energie oder Zeit dafür, um es dir gleichzutun. Und es ist leider auch so, dass das alte selfHtml sehr allein da stand, heute dagegen zumindest das MDN eine verdammt gute Alternative zu selfHtml darstellt. Wenn sogar die Artikel im Wiki dorthin als Referenz verlinken...
Gruß Rolf
Servus!
Hallo Matthias,
ich wollte dich nicht frustrieren. Es ist Wahnsinn, wieviel Arbeit du hier investierst, und leider hat nicht jeder die Energie oder Zeit dafür, um es dir gleichzutun. Und es ist leider auch so, dass das alte selfHtml sehr allein da stand,
Ja, da ist von 2007- 2010 oder 2014 viel liegengeblieben, was jetzt aber langsam aufgeholt ist.
heute dagegen zumindest das MDN eine verdammt gute Alternative zu selfHtml darstellt.
Ja, wobei nicht alles übersetzt ist und viele Artikel seit der Veröffentlichung wohl nicht mehr gepflegt wurden. Gerade beim Browser-Support sind wir mit der Verlinkung auf Caniuse besser dran.
Wenn sogar die Artikel im Wiki dorthin als Referenz verlinken...
Haben wir früher nicht gemacht, aber irgendwie sind die MDN-Artikel und die Links auf die Spec doch Mehrwert. Gerade die Wikipedia ist da Vorbild, wie viel Quellen die mittlerweile haben.
Mir tut's in der Seele weh, dass Stefan Münz die Leute 2003 aufgefordert hatte, doch zur Wikipedia zu gehen und dort was schreiben.
Herzliche Grüße
Matthias Scharwies
Lieber Matthias,
Mir tut's in der Seele weh, dass Stefan Münz die Leute 2003 aufgefordert hatte, doch zur Wikipedia zu gehen und dort was schreiben.
mittlerweile verlinken die in ihren Weblinks auf unser Wiki mit dem Hinweis
CSS. selfhtml.org, 6. Juni 2014, abgerufen am 24. September 2014 (deutsch, Ausführliche Darstellung zusammen mit HTML).
Liebe Grüße,
Felix Riesterer.
nabend Felix,
wo finde ich hier ein Tutorial für JS Patterns?
was sind "JS Patterns"? Meinst Du vielleicht reguläre Ausdrücke in JS?
Liebe Grüße,
das was Rolf gepostet hat "Design Patterns". Sry wenn der Begriff nicht deutlich geworden ist.
Herzlichste Grüße MB
Servus!
wo finde ich hier ein Tutorial für JS Patterns?
das was Rolf gepostet hat "Design Patterns".
Ich habe mal
angelegt und von der einen Stelle, die es schon erwähnt, auch verlinkt. Das wäre aber bestimmt auch einen eigenen Artikel in Programmiertechnik wert.
Herzliche Grüße
Matthias Scharwies