ToraxMalu: Frage zum Wiki-Artikel ‚new‘ - Prototypenbeschreibung

problematische Seite

Moin!

Der Teilabschnitt mit new ist soweit noch klar und verständlich. Beginnt es dann aber mit dem Prototypen, explodiert einem der Kopf.

  1. Mit immer ähnlicheren Begriffe wird der Prozesses verklärt. Es ist nicht klar, was gemeint wird.
  2. Die Schachtelsätze passen einfach nicht ins Hirn… :D

Könnt ihr das bitte etwas umformulieren? Ich versuche es auf jeden Fall morgen noch mal zu verstehen.

Merci

ToraxMalu

  1. problematische Seite

    Tja, was soll man da sagen. Wer an OOP in der Art von C++ oder Java gewöhnt ist, muss bei Prototypen erstmal umdenken. Siehe den Link unten für Einstiegshilfen.

    Das Thema "new" ist wirklich schwierig. Wenn man nur sagt "es aktiviert den Konstruktormodus einer Funktion und stellt das konstruierte Objekt in this zur Verfügung", ist kaum was gesagt. Will man mehr sagen, steckt man sofort in einer Detailbetrachtung zu all den Quirks und Besonderheiten der Vererbungslehre von Javascript.

    Für Konzepte wie "Was sind Prototypen" und "Wie funktioniert Vererbung in JavaScript" gibt's auch Tutorials. Schau mal hier unter Grundlegende Konzepte.

    Rolf

    1. problematische Seite

      Moin Rolf,

      danke für den Link, der war mir entgangen.

      Java? C++? Zeilennummern und Spaghetticode! ;)

      Im Ernst: Dass new ein neues Objekt erstellt und dann in diesem Kontext die Funktion die Objekt-Bestandteile zusammenbaut und initialisiert, ist verständlich. Auch die Konstruktion mit this erschließt sich recht gut. Ich bekam nur gestern mit den Schachtelsätzen im zweiten Teil dieser Einführung Probleme. Ich versuche es noch mal, und gebe noch mal Feedback.

      Der Vorteil von SelfHTML sind die immer wieder erklärten technischen Abläufe – nur manchmal wählen die Techniker für Neulinge die falschen Worte. Zumindest erlebe ich es selbst im Umgang mit Neulingen dieses Phänomen.

      Cheers

      ToraxMalu

      1. problematische Seite

        Hallo ToraxMalul,

        Der Vorteil von SelfHTML sind die immer wieder erklärten technischen Abläufe – nur manchmal wählen die Techniker für Neulinge die falschen Worte. Zumindest erlebe ich es selbst im Umgang mit Neulingen dieses Phänomen.

        Dem entnehme ich, dass du selbst kein Neuling auf diesem Gebiet bist. Du kannst gern Änderungen am Artikel vornehmen. Eine einfachere (und dabei aber dennoch richtige) Formulierung ist sicherlich hilfreich.

        Bis demnächst
        Matthias

        --
        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
        1. problematische Seite

          Okay, I give up. Der Code lässt erahnen, was gemeint ist, aber aus dem Text werde ich irgend wie nicht wirklich schlau. (Gemeint ist https://wiki.selfhtml.org/wiki/JavaScript/Operatoren/new#Beschreibung ab der Textstelle „Wenn es allerdings nur darum ginge, durch eine Funktion Objekte…“)

          Oder habe ich das richtig verstanden:

          1. Ich "bastle" einen Konstruktor [Objektname]
          2. Dann lege ich die Methoden nicht unter [Objekt.methode] ab, sondern unter [Objekt.prototype.methode]
          3. Führe ich dann ein new [Objektname] aus, werden die Methoden aus [Objekt.prototype] an das neue Objekt „vererbt“, ohne noch einmal im Speicher definiert zu werden.

          Der Konstruktor darf nur kein anderes Objekt als Rückgabewert generieren / enthalten.

          1. problematische Seite

            Okay, man werde nicht vorschnell die Flinte ins Korn werfen…

            function a() {
            	this.Juhu = "Na Danke";
            }
            
            a.prototype.zeige = function () {
            		console.log(this.Juhu);
            }
            
            var b = new a;
            

            Wenn ich die Ausgaben richtig interpretiere:

            b; //Object b{"Na Danke"}
            b.zeige(); //"Na Danke"
            b.zeige; //function a.prototype.zeige()
            

            scheine ich das Prinzip richtig zu verstehen. Kann das sein?

            1. problematische Seite

              Tach!

              scheine ich das Prinzip richtig zu verstehen. Kann das sein?

              Ja, so geht das. Versuch doch mal nun, ob du den Text so formulieren kannst, dass du den gleich von Anfang an verstanden hättest.

              dedlfix.

            2. problematische Seite

              Ja, grundsätzlich schon. Ich hätte aber noch den Hinweis, dass man Konstruktorfunktionen per Konvention groß schreibt, um sie von normalen Funktionen zu unterscheiden.

              Der entscheidende Punkt ist, dass jedes Objekt - wirklich jedes - ein verborgenes Property für den Prototyp hat. Dieses verborgene Property darf man übrigens NICHT mit der prototype-Eigenschaft einer Konstruktorfunktion verwechseln!

              Manche Laufzeitumgebungen stellen dieses Property als __proto__ bereit - das ist aber non-standard. Der offizielle Weg zum Prototypen ist Object.getPrototypeOf(x). Und wenn man dann das Property foo des Objekts, das in bar steht, LESEN will, beginnt die JS Laufzeitumgebung mit der Suche.

              • Ist 'foo' in bar vorhanden?
              • Ist 'foo' in Object.getPrototypeOf(bar) vorhanden?
              • Ist 'foo' in Object.getPrototypeOf(Object.getPrototypeOf(bar)) vorhanden?

              und so weiter. Da Methoden nichts weiter sind als Funktionen, die als Eigenschaft eines Objekts gespeichert sind, funktioniert diese Suchkette für Datenproperties genauso wie für Methoden.

              Wenn man ein Property schreiben will, wird immer nur am Objekt selbst geschrieben. Durch Operationen am Objekt selbst wird der Prototyp nicht verändert.

              Nun stellt sich die Frage, wo der Wert herkommt, der im Prototyp in der property-Eigenschaft eines Objekts steht. Wird ein Objekt neu erzeugt, kann man den Prototypen explizit angeben:

              var a = { foo: 17 };
              var b = Object.create(a);
              /// Object.getPrototypeOf(b) === a ---> true
              

              a ist jetzt der Prototyp für b. a selbst hat auch einen Prototypen, und zwar das Objekt, das in Object.prototype zu finden ist. DIESES Objekt ist wiederum das einzige Objekt in der JavaScript-Objektsuppe, dessen Prototyp leer ist (genauer gesagt: das interne Prototyp-Property enthält den Wert null).

              Object.create nutzt man aber eher selten. Im Normalfall verwendet man den new Operator. Oder ein Objektliteral, was aber Syntaxzucker ist für new Object(). Den new-Operator kannst Du Dir vereinfacht vorstellen als

              var newObject = Object.create(Constructor.prototype);
              Constructor.apply(newObject, constructorArgs);
              return newObject;
              

              Diese Vereinfachung lässt einiges außer Acht, vor allem den Rückgabewert der Konstruktorfunktion. Die Details stehen in der JavaScript-Spec, viel Spaß beim Decodieren...

              Wenn Du eine eigene Funktion Bar erzeugst, bekommt sie von JavaScript automatisch eine neues Objekt als prototype-Property zugewiesen. Dieses Prototypobjekt kannst Du erweitern, kannst es aber auch komplett überschreiben. Benutzt Du dann new Bar(), so bekommt das erzeugte Objekt den Prototypen Bar.prototype. Aber nicht vergessen, Bar.prototype ist NICHT der Prototyp von Bar.

              // Object.getPrototypeOf(Object) === Object.prototype -> false
              // Object.getPrototypeOf(Object) === Function.prototype -> true!
              
              var a = { foo:17 };
              // Object.getPrototypeOf(a) === Object.prototype -> true
              
              var b = Object.create(a);
              // Object.getPrototypeOf(a) === a -> true
              
              function Bar = function() { };
              Bar.prototype = { baz:99 };
              var c = new Bar();
              // Object.getPrototypeOf(c) === Bar.prototype -> true
              // Object.getPrototypeOf(c) === Object.getPrototypeOf(Bar) -> false
              // Object.getPrototypeOf(Bar) === Object.getPrototypeOf(Function) -> true
              

              Interessant ist auch die Frage, ob es sinnvoller ist, Methoden am Prototyp zu definieren oder sie in der Konstruktorfunktion als Eigenschaften zuzuweisen. Beides geht, aber der Effekt ist unterschiedlich.

              • Weise ich sie in der Konstruktorfunktion zu, passiert das bei jedem new-Aufruf. Muss ich viele Objekte zu dieser Konstruktorfunktion erzeugen, kostet das deutlich Zeit. Stehen die Methoden am Prototyp, geschieht das nur einmal und damit schneller
              • Andererseits kann ich in Methoden, die in der Konstruktorfunktion definiert werden, auf lokale Variablen der Konstruktorfunktion zugreifen und damit echt private Objekteigenschaften realisieren. Methoden, die auf dem Prototypobjekt definiert sind, können das nicht.
              • Füge ich den Prototyp eine Eigenschaft oder eine Methode hinzu, gilt diese sofort für alle Objekte, die diesen Prototypen verwenden.

              Das class Keyword von ECMAScript 6 ist übrigens nur Syntaxzucker für eine Konstruktorfunktion.

              So, ich hoffe, dass ich jetzt alle Klarheiten endgültig beseitigt habe. Es steht auch alles im WIKI, aber manchmal hilft auch eine andere Formulierung des gleichen Sachverhalts :)

              Rolf

              1. problematische Seite

                /me murmelt: Oh ja, die Klarheiten sich wirklich beseitigt :D

                Ich habe mal den Bereich umformuliert. Schaut es euch bitte an, ob ich da in meinem Halbwissen Müll geschrieben oder es besser getroffen habe. Der Punk mit lokalen Variablen könnte vielleicht noch erwähnt werden, wobei ich aus meiner Warte gerade keinen Sinn darin sehe. Sind Objekte-Eigenschaften nicht generell von außen erreichbar und eine Kapselung erst durch eine Funktion möglich?

                1. problematische Seite

                  /me murmelt: Oh ja, die Klarheiten sich wirklich beseitigt :D

                  Der Punk mit lokalen Variablen ...

                  Made My Day :D

                  1. problematische Seite

                    /me murmelt: Oh ja, die Klarheiten sich wirklich beseitigt :D

                    Der Punk mit lokalen Variablen ...

                    Made My Day :D

                    Schön, wenn ich deinen Tag versüßte… :D Aber um ehrlich zu sein, war ich von deinen Ausführungen genauso erschlagen, wie von den Schachtelsätzen in dem Artikel.

                    Cheers.

                    1. problematische Seite

                      Hast Du mal den hier:

                      https://wiki.selfhtml.org/wiki/JavaScript/Vererbung

                      gelesen? Da wird auf Prototypen und Vererbung intensiv eingegangen. Wenn Du diesen Artikel für verständlicher hältst, dann könnte man überlegen, den Artikel zu "new" massiv zu beschneiden und statt dessen auf den Vererbung-Artikel zu verlinken.

                      Das Thema mit Objekteigenschaften wird in einem Nachbarartikel dazu behandelt, dass muss man unter new nicht bringen.

                      Rolf

                      1. problematische Seite

                        Weia - und dafür habe ich mich 1¹/₂ Tage durchgebissen‽

                        Da könnte man wirklich einiges aus dem new-Artikel entfernen und auf diese Seite verweisen. Nur die Prototypenerklärung, in welcher Reihenfolge new mit dem Prototypen arbeitet und die Gefahr mit return {} in der Konstruktor-Funktion sollten unbedingt unter new erhalten bleiben.