JavaScript-Vererbung aus der Sicht eines gelangweilten Nerds: Constructors Factory

Lampe des Lichts und Apfel der Zwietracht Dies ist eine Geschichte über ein ganz besonderes Stück JavaScript, die heute weltweit am häufigsten verwendete künstliche Sprache (2019).

Der Artikel präsentiert eine Art philosophische Sicht der Vererbung in JavaScript, und ich wage nur zu hoffen, dass sie auf der beeindruckendsten Wissensquelle basiert: dem Leben selbst in all seinen Erscheinungsformen. Ich weiß nicht, ob dies eine Inspiration für die Erstellung des Prototyp-Kettenentwurfs in JavaScript war.

Aber wenn ja, dann ist es so bedeutsam und kraftvoll, dass es manchmal sogar schwierig wird zu atmen, wenn ich darüber nachdenke ...

(Alle Links sind unterstrichen )


Ich bin mir auch sicher, dass keiner von uns daran zweifeln wird, dass Brendan Ike (Eich) - der Autor der JavaScript-Programmiersprache - ein herausragendes Genie ist! Und das nicht nur, weil er oft wiederholt:
Wetten Sie immer auf JavaScript!
Fangen wir an! Und unser erster Ausgangspunkt wird Imagination sein, bei dem wir zuerst alle Vorurteile, Auslassungen und andere Nebenwirkungen ausschalten.

Wir gehen zurück in die Zukunft , die Ära vor der Schaffung des modernen Internets in den frühen neunziger Jahren.

Seit der Zeit der ersten Hacker, die alles erfunden haben, was wir ( IT-Mitarbeiter ) jetzt verwenden , haben wir uns einer beeindruckenden Skizze zugewandt : dem Krieg zwischen den Browsern Netstcape Navigator 2 und Internet Explorer 3. Java ist gerade herausgekommen, und fast alles aus dem modernen Internet wurde noch nicht erfunden oder nicht vorgeöffnet. Es ist möglich, dass Sie wie ich in diesen „guten alten Tagen“ jung waren und sich an dieses wunderbare Gefühl der Beteiligung an all der Pracht erinnern konnten, die direkt vor Ihren Augen entsteht.

Sie haben also einen sehr leistungsstarken PC auf dem modernsten Intell Pentium 200 MMX mit 32 MB RAM, Windows 3.11 oder sogar Windows 95 und blicken mit Hoffnung in die Zukunft! Natürlich sind auch beide Browser installiert. Sie haben eine Einwahl , über die Sie auch eine Verbindung zum Netzwerk herstellen, um neuen Müll zu erhalten, um zu lernen oder einfach nur zu chatten, zu chatten. Obwohl Sie immer noch nicht direkt im Browser chatten können, verwenden Sie höchstwahrscheinlich Systeme zur verzögerten Nachrichtenübermittlung, z. B. EMail oder UseNet , oder Sie haben möglicherweise bereits die sofortige Zustellung über IRC gemeistert.

Ein paar Jahre vergehen und buchstäblich ALLES ändert sich ... Plötzlich sehen Sie die Animation von Schneeflocken auf den Webseiten, die Ihnen zu Neujahr und Weihnachten gratulieren. Natürlich interessiert Sie, wie das gemacht wird, und Sie entdecken eine neue Sprache - JavaScript. Da HTML für Sie nicht neu ist, lernen Sie dieses verführerische Techno-Handwerk. Bald entdecken Sie CSS und es stellt sich heraus, dass dies auch wichtig ist, da jetzt alles aus einer Kombination dieser drei Elemente besteht: HTML, JavaSript und CSS. Wow.

Etwa zur gleichen Zeit bemerkten Sie möglicherweise einige großartige Dinge in Windows selbst, CScript und HTA wurden darin angezeigt , und selbst dann wurde es möglich, vollwertige Desktop-Anwendungen direkt auf JS zu erstellen (und dies funktioniert immer noch).

Und so haben Sie begonnen, Ihren ersten Webserver zu erstellen, möglicherweise in Perl oder C ~ C ++ . Vielleicht haben Sie sogar angefangen, Unix-ähnliche Betriebssysteme zu verwenden und dies auf Bash zu tun. Und das alles dreht sich dank der Common Gateway-Schnittstelle (verwechseln Sie es nicht mit dem anderen CGI ). PHP gibt es fast immer noch nicht, aber vielleicht wird es Ihnen bald gefallen.

200x Ära. Sie führen jetzt ASP in JScript aus . Dies ist dem JavaScript sehr ähnlich, das auf Ihren Webseiten funktioniert. Das ist so cool! Sie überlegen, eine eigene Template-Engine zu erstellen, eine Art XML- Parodie. Und dann ruft plötzlich jemand AJAX an , um Inhalte, die Sie seit mehreren Jahren verwenden, dynamisch zu laden. Und alle denken jetzt, dass es nur XMLHTTPRequest gibt , aber Sie denken daran, dass die Daten an BMP , IFrame oder sogar durch Einfügen des <script> -Tags übertragen werden können . Und dann spricht plötzlich jemand begeistert über JSON und wie nützlich es ist, wenn Sie Daten für eine Ewigkeit mit so etwas gefahren haben:

document.write("<" + "script src=" + path + ">"); 

Es ist jetzt alles nicht wichtig, aber Sie können sich immer noch daran erinnern, wie ...

Wenn Sie zur Besinnung kommen, stöbern Sie von Zeit zu Zeit mit Rhino oder Nashorn herum, um die Wünsche von Java-Kunden mit Alfresco oder Asterisk zu erfüllen. Und Sie haben bereits von dem bevorstehenden Aufkommen von JavaScript in der Welt der Mikrochips gehört und sind von diesen Neuigkeiten sehr inspiriert. Und jetzt haben Sie natürlich jQuery und Backbone .

Wenn Sie den Schneefall des kommenden Jahres 2010 beobachten, wissen Sie bereits, dass sich in Ihrer Welt alle Spielregeln bald ändern werden, da „Spieler Nr. 1“ das Feld betreten hat: Node.js. Und die nächsten 10 Jahre werden Sie mit diesem neuen Spielzeug verbringen, und selbst jetzt, im Jahr 2019, können Sie immer noch nicht genug davon bekommen, wie cool es ist.

Im Allgemeinen sind Sie mit allem zufrieden, alles passt zu Ihnen, all diese Spielzeuge und Spiele machen einen großen Teil Ihrer Lebensinteressen aus.

Aber es gibt eine kleine Frage, die Sie sich seit zwei Jahrzehnten Tag für Tag und Nacht für Nacht stellen:

Wenn Sie dies tun müssten, wie würden Sie Empathie mit JavaScript erklären?


Sie wissen, dass eines der kompliziertesten Themen in JavaScript die Vererbung von Prototypen und die Prototypenkette ist . Und Sie lieben dieses Thema, Sie können erklären, wie alles funktioniert und funktioniert, einfach weil Sie es fast von Anfang an gelernt haben, noch bevor die erste Version des Standards geboren wurde, und wo es, wie Sie sich erinnern, 4.2 gibt .1 Objekte :
ECMAScript unterstützt die prototypbasierte Vererbung. Jedem Konstruktor ist ein Prototyp zugeordnet, und jedem von diesem Konstruktor erstellten Objekt ist implizit ein Verweis auf den Prototyp (als Prototyp des Objekts bezeichnet) zugeordnet, der seinem Konstruktor zugeordnet ist. Darüber hinaus kann ein Prototyp einen impliziten Verweis ungleich Null auf seinen Prototyp haben und so weiter; Dies wird als Prototypkette bezeichnet .
Jedes Objekt wird mit einem impliziten Verweis auf den Prototyp erstellt. Dies wird als Prototyp-Vererbungskette bezeichnet, die Sie so lange fortsetzen können, wie Sie möchten.

Wow ... Und wenn Sie plötzlich wie ich denken, dass dies eine der größten Erfindungen in der Compuer Science ist , wie würden Sie dann die Wirkung ausdrücken, die das Lesen dieser Aussage auf Sie hatte?

Kehren wir zum Anfang zurück. Auf dem Hof ​​1995. Sie sind Brendan Ike und müssen eine neue Programmiersprache erfinden . Vielleicht magst du Lisp oder Scheme , zumindest einige ihrer Lieblingsteile. Und Sie stehen vor der Notwendigkeit, das Problem der Vererbung zu lösen, da Sie so tun müssen, als ob die Sprache eine bestimmte Implementierung von OOP hat . Denken wir mal : Sie müssen alle Dinge mischen, die Sie mögen, vielleicht auch einige Dinge, die Sie nicht mögen, und der resultierende Cocktail sollte gut genug sein, damit niemand einen Trick bemerkt, bis es wirklich notwendig ist, zu verstehen, wie er ist innen angeordnet.

Und jetzt ist die Frage: Was würde mit der Vererbung passieren?

Kommen wir für einen Moment zur Realität zurück. Was wissen wir alle über Vererbung? Einige offensichtliche Antworten auf diese Frage:

  1. Die meisten lebenden Formen basieren auf dem Genom . Es ist eine solche Sammlung von Informationen über die wahrscheinlichen Merkmale und das angebliche Verhalten von Lebewesen. Wenn Sie ein Lebewesen sind, tragen Sie einen Teil des Genoms in sich, Sie können es verteilen, aber Sie haben es von früheren Generationen erhalten.
  2. Sie können ein Lebewesen mit zwei Techniken erstellen: Mischen (Genome) zweier Vorfahren oder möglicherweise das monözische Klonen eines dieser Vorfahren. Natürlich sind heute Technologien verfügbar, mit denen die Genome von mehr als einer Kreatur gemischt werden können, aber dies ist viel weniger offensichtlich und nicht so natürlich.
  3. Der Zeitfaktor ist wichtig. Wenn es keine geerbte Eigenschaft gibt oder noch nicht, besteht unser einziger Ausweg darin, sie von Grund auf neu zu erstellen. Darüber hinaus gibt es auch das Vermächtnis, das von seinen Vorfahren nicht durch das Genom, sondern durch die Gesetze des Eigentums auf das Wesen übergeht, und dies kann auch von Bedeutung sein.

Zurück in die Vergangenheit und die richtige Frage, die wir uns stellen müssen, lautet jetzt: Und tatsächlich Vererbung Was wollen wir bekommen?

Nun, auf jeden Fall müssen wir bei der Lösung des Vererbungsproblems zumindest die Lücke zwischen Programmierung und realem Leben schließen, sonst haben wir im Allgemeinen kein Recht, es Vererbung zu nennen.

Lassen Sie uns jetzt fertig werden: Wir sind in den 1995er Jahren und haben einen leistungsstarken PC mit nur 32 Megabyte RAM. Wir versuchen, eine interpretierte Sprache zu erstellen, daher müssen wir uns sehr um diesen Speicher kümmern. Jedes Datenelement, insbesondere String-Objekte , verbraucht viel Speicher, und wir sollten dieses Element nur einmal deklarieren können. Wenn möglich, sollten Sie in Zukunft immer nur Zeiger auf den Speicherbereich verwenden, der von diesem Element belegt wird. Wir fassen zusammen: eine sehr schwierige Frage.

Es gibt eine populäre Meinung: " JavaScript wird aus Objekten erstellt ." Mit dieser Trivialität können wir sehr einfach die Frage „ von was “ zu erben und „ was “ beantworten: von Objekten zu Objekten. Um Speicherplatz zu sparen, müssen alle Daten in diesen Objekten gespeichert werden, und alle diese Datenverknüpfungen müssen auch in den geerbten Eigenschaften dieser Objekte gespeichert werden. Vielleicht ist jetzt klar, warum wir 1995 wirklich ein Design erstellen mussten, das auf einer Prototypenkette basiert: Es spart so lange Speicherplatz wie möglich! Und im Allgemeinen denke ich, dass dies immer noch ein sehr wichtiger Aspekt sein kann.

Basierend auf dem angegebenen Design und der Meinung „ Alles ist ein Objekt “ können wir versuchen, so etwas zu klonen. Aber was klont hier jetzt? Ich denke, dass wir gemäß den Anforderungen unserer Anforderungen so etwas wie Struktur- oder Oberflächenkopie annehmen können, ähnlich wie die Vorgänger des modernen Object.assign .
Lassen Sie uns 1995 eine einfache Strukturkopie mit for (var i in) {} implementieren, da der Standard dies bereits zuließ :

 // back in 1995 cloning // it is not deep clone, // though we might not need deep at all var cloneProps = function (clonedObject, destinationObject) { for (var key in clonedObject) { destinationObject[key] = clonedObject[key]; } }; 

Wie Sie sehen, funktioniert dieser Ansatz immer noch, obwohl ich im Allgemeinen natürlich empfehlen würde, das Deep-Extend- Modul zu betrachten, um ein detaillierteres Verständnis für das Klonen in JavaScript zu erhalten. Für die Zwecke des Artikels ist jedoch eine konsistente Anwendung für uns durchaus geeignet beschrieben von cloneProps , weil wir es in jenen alten Zeiten gut gebrauchen konnten:

  • Klonen von Objekten mit dem Konstruktor: Erstellen Sie mit dem Konstruktor mindestens zwei verschiedene Klone

     // cloneProps is described above var SomeConstructor = function (clonedObject) { cloneProps(clonedObject, this); }; var someExistingObjectToClone = { foo : 'bar' }; var clone1 = new SomeConstructor(someExistingObjectToClone); var clone2 = new SomeConstructor(someExistingObjectToClone); // clone1.foo == clone2.foo 
  • Klonen eines Konstruktors von einem Konstruktor: Wir implementieren die Verwendung des Verhaltens eines Konstruktors von einem anderen Konstruktor

     var SomeConstructor = function () { this.a = 'cloned'; }; var AnotherConstructor = function () { // Function.prototype.call // was already invented in 1st ECMA-262 SomeConstructor.call(this); }; 
  • Klonen eines Konstruktors mithilfe eines Objekts: Wir verwenden dasselbe Objekt, um das Klonen in mindestens zwei Konstruktoren zu implementieren

     var existentObject = { foo : 'bar' }; var SomeConstructor = function () { cloneProps(foo, this); }; var OtherConstructor = function () { cloneProps(foo, this); }; 
  • Klonen eines Objekts von einem anderen Objekt: Verwenden Sie ein Objekt, um mehrere seiner Klone zu erstellen . Hier gibt es nichts zu beschreiben, nehmen Sie es einfach so wie unsere cloneProps aus dem ersten Beispiel oben.

Beim Klonen ist im Allgemeinen alles einfach, wie wir sehen, alles ist klar und im Allgemeinen, aber ...

Ist es für uns so einfach, die Vererbung von Entitäten mit einer Kombination ihrer Vorgänger durchzuführen?

  • Vererbung eines Objekts mit dem Konstruktor: Dies ist der eigentliche Zweck der Designer. Wir werden nur zeigen, wie es ursprünglich entworfen wurde .

     var existentObject = { foo : 'bar' }; var SomeConstructor = function () {}; SomeConstructor.prototype = existentObject; var inheritedObject = new SomeConstructor(); // we have no instanceof yet in ECMA 262 of 1995 // therefore we are unable to rely on this window.alert(inheritedObject.foo); // bar 
  • Vererbung des Konstruktors von einem anderen Konstruktor: Ohne Zweifel war der erste, der dies bemerkte, ein herausragendes Genie. Alles in allem ist dies ein weiteres klassisches Beispiel von überall .

     var FirstConstructor = function () { this.foo = 'bar'; }; var InheritedConstructor = function () { FirstConstructor.call(this); }; InheritedConstructor.prototype = { bar : 'foo' }; InheritedConstructor.prototype.constructor = FirstConstructor; var inherited = new InheritedConstructor(); // { foo : 'bar', bar : 'foo' } 

    es wäre möglich, etwas Anspruchsvolles zu sagen, aber warum
  • Vererbung des Konstruktors vom Objekt: Auch hier verwenden wir jedes Mal, wenn wir es benötigen, nur .prototype = object. Es gibt nichts zu beschreiben. Wir müssen immer Constructor.prototype zuweisen, da es das Objekt dort ablegen soll, und durch einen impliziten Link erhalten wir alle seine Eigenschaften .
  • Ein Objekt von einem Objekt erben: dasselbe. Wir haben gerade das erste Objekt in Constructor.prototype eingefügt und sobald wir new Constructor sagen, erstellen wir eine geerbte Kopie, in der implizite Verweise auf die Eigenschaften unseres ersten Objekts enthalten sind.

Und natürlich haben wir in all diesen Situationen mit Vererbung die Möglichkeit, anhand der Instanz zu überprüfen, aus welchem ​​Konstruktor wir die Objekte erstellt haben, obwohl natürlich zu beachten ist, dass die Instanz selbst fast vier Jahre später in den Standards auftauchte.

Zwar blieb aus Absatz 4.2.1 ein so kleines Detail übrig:
in der Lage sein, dies so lange wie nötig zu tun, wie es heißt:
und so weiter
Lassen Sie uns versuchen, die Vererbung mithilfe der Technologie von 1995 wirklich endlos zu machen .

Stellen wir uns vor, wir haben zwei Entitäten und nicht Konstruktoren, sondern einfache Objekte. Und wir wollten eins vom anderen erben und dann vielleicht vom anderen und vom anderen und so weiter ...

Aber wie?


Schauen Sie etwas weiter und tiefer.
Die richtige Antwort lautet auch hier: Vererbung dessen, was wir schaffen müssen?

Schließlich brauchen wir diese Entitäten nicht alleine. Wir brauchen ihre Eigenschaften: zugehöriger Datenverbrauch; und wahrscheinlich brauchen wir auch ein Verhalten: Methoden, die diese Daten verwenden. Und es wird genauso ehrlich sein , wenn wir die Möglichkeit haben, zu überprüfen, wo und wo wir geerbt haben und was zu verwenden. Im Allgemeinen wird es genauso cool sein, wenn wir das inhärente Design der Vererbungsmuster in Zukunft reproduzieren könnten, was bedeutet, dass wir, wenn wir viele Male voneinander erben, immer das gleiche Ergebnis erhalten, gemäß dem, was wir geschrieben haben (Vertrag) . Obwohl dies immer noch der Fall ist, kann es für uns genauso nützlich sein, den Moment der Schöpfung irgendwie festzulegen, da sich unsere „vorherigen“ Entitäten im Laufe der Zeit ändern können und sich die „Erben“, die ihnen diesbezüglich Respekt zollen, immer noch mit ihnen ändern kann wohl nicht ganz wollen.

Und da unser gesamter Code eine Kombination aus Daten und Verhalten ist, ist es im Allgemeinen normal, beim Entwurf eines Vererbungssystems dieselbe Methode zu verwenden - Daten und Präsentation zu kombinieren?

Für mich ähnelt dies alles dem, was wir sehen, wenn wir das Leben in all seinen unglaublichen Formen beobachten. Von der ersten einzelligen bis zur mehrzelligen und ihren Nachkommen und weiter zu Tieren, Menschen, Humanismus und Stämmen, Zivilisationen, Intellekt und seinen künstlichen Formen und weiter zum Weltraum, zur Galaxie, zu den Sternen! und:
"... Alles was wir tun müssen ist sicherzustellen, dass wir weiter reden ..."
(Alles was wir tun müssen, ist die Kommunikation fortzusetzen)

Unglaublich in seiner Nachdenklichkeit, ein Zitat von Stephen Hawking , das später in diesem Pind Floyd- Meisterwerk populär wurde.

Mit Programmiersprachen, die auf der Weitergabe von Nachrichten und einem Flow-basierten Konzept basieren , das über eine robuste interne API implementiert wird, können Sie von einfachen Daten zu höheren Abstraktionen, Beschreibungen und allem anderen wechseln. Ich denke, dies ist reine Kunst und wie sie insbesondere in tief verborgenen JavaScript-Strukturen durch implizite Beziehungen zwischen Daten in Prototypenketten funktioniert.

Stellen Sie sich noch einmal zwei Vorfahren vor, sie kommunizieren und in einem Moment schaffen ihre Gefühle und Emotionen ein Kind. Das Kind wird erwachsen, trifft ein anderes Kind, sie kommunizieren und der nächste Nachkomme erscheint und dann weiter und weiter und weiter ... Und wir brauchen immer zwei Eltern, sonst ist es nicht natürlich, es wird bereits Gentechnik sein. Zwei, nicht mehr und nicht weniger. Ein Nachkomme erhält dasselbe wie sein Vermächtnis, es ist also einfach und verständlich.

Ich verstehe, dass es seltsam klingen wird, aber ja, wir haben alles, was wir brauchen, um dieses Erbschaftsmodell 1995 zu schaffen. Und die Basis all dessen sind genau 4.2.1 Objekte , implizite Referenzierung durch Prototyp.

Und genau das ist es, wenn Sie ParentObject mit ParentConstructor kombinieren, indem Sie .prototype angeben, und dann wird Constructor uns wahrscheinlich ein ChildObject erstellen, wenn wir das Zauberwort " neu " sagen:

 var ParentObject = { foo : 'bar' }; var ParentConstructor = function () {}; ParentConstructor.prototype = ParentObject; var ChildObject = new ParentConstructor(); // starting from 1995 and then ECMA 262 // we are able to say new // each time we need a ChildObject 

Wir können hier unsere beiden Vorfahren erkennen. In dem Moment, als wir das Zauberwort " neu " sagten, baten wir sie, sich zu unterhalten. Wenn sie nicht kommunizieren möchten, stoppt das Leben, der Prozess fällt mit einem Fehler ab und der Compiler (Interpreter) teilt uns dies mit.

Natürlich, ja, aber wir haben nach dem Vererbungsbaum gefragt oder es offensichtlich viel einfacher sein lassen, zumindest für den genealogischen Baum. Und die Antwort ist immer noch dieselbe ... unser untergeordnetes Objekt wird erwachsen und wird zu einem übergeordneten Objekt . Dann trifft es auf ein neues Konstruktorobjekt und sobald wir das begehrte Wort " neu " sagen - Magie:

 // this Assignment is just to show it grew up var ChildObjectGrownToParent = ChildObject; var AnotherConstructor = function () {}; AnotherConstructor.prototype = ChildObjectGrownToParent; var SequentialChildObject = new AnotherConstructor(); // checking Life Cycle ;^) console.log(ChildObject instanceof ParentConstructor); // true console.log(SequentialChildObject instanceof ParentConstructor); // true console.log(SequentialChildObject instanceof AnotherConstructor); // true 

Und wir können dies ad infinitum fortsetzen. Und ich glaube vielleicht wirklich, dass dies die Hauptidee bei der Entwicklung des Designs der Prototypenkette war, denn wie wir alle wissen, verursacht dieser Ansatz einige sehr ordentliche, aber nicht weniger unangenehme Probleme ...

1: Community ... Wie Sie leicht selbst überprüfen können, ist die Angabe in .prototype ParentConstructor ' a oder AnotherConstructor' a ein sehr ernsthafter und strenger Gesellschaftsvertrag in unserem Stamm. Es wird ein Verweis auf die ParentObject ( .foo ) -Eigenschaften für die Erben ChildObject und SequentialChildObject erstellt . Und wenn wir diesen Hinweis loswerden, verschwinden diese Links. Wenn wir diesen Verweis erfinden und einem anderen Objekt zuweisen, erben unsere Erben sofort andere Eigenschaften. Wenn wir also Vorfahren durch .prototype kombinieren, können wir wahrscheinlich sagen, dass wir eine Art Zelle der Gesellschaft schaffen , weil diese „Vorfahren“ jedes Mal, wenn wir sie mit new danach fragen, viele identische Nachkommen reproduzieren können. Und so, nachdem wir die "Familie" zerstört haben, ruinieren wir die erblichen Eigenschaften seiner Nachkommen, ein solches Drama; ^)

Vielleicht geht es hier nur um Legacy in unserem Code. Wir sollten uns darum kümmern, wenn wir einen sicheren und unterstützten Code erstellen wollen! Natürlich wurden 1995 kein SOLID , Liskov-Prinzip und Design by Contract sowie GRASP diskutiert, aber es ist offensichtlich, dass diese Methoden nicht „von Grund auf neu“ erstellt wurden, sondern alles begann viel früher.

2: Familie ... Wir können leicht überprüfen, ob unser ParentObject mit anderen Constructos sehr frivol sein darf. Dies ist nicht fair, aber wir können so viele Konstruktoren verwenden, wie wir für die Vererbung unseres ParentObject wünschen, und so so viele Familien erstellen, wie wir möchten. Andererseits ist jeder Konstruktor über die .prototype-Aufgabe sehr eng mit ParentObject verbunden. Wenn wir unseren Erben keinen Schaden zufügen möchten, müssen wir diese Verbindung so lange wie möglich aufrechterhalten. Wir könnten es die Kunst der Tragödie in der Geschichte unseres Stammes nennen. Obwohl dies uns natürlich vor Amnesie schützt - der Vergesslichkeit dessen, was wir geerbt haben und von wem und warum unsere Erben solch ein Vermächtnis erhalten . Und wir loben den großen Mnemosyne ! Wir können unseren Prototyp-Kettenbaum wirklich leicht testen und Artefakte von dem finden, was wir falsch gemacht haben.

3: Alter ... Unser ParentObject und unser Konstruktor sind während des Lebenszyklus unseres Programms sicherlich anfällig für Schäden. Wir können versuchen, uns darum zu kümmern, aber niemand ist vor Fehlern sicher. Und all diese Veränderungen können den Erben schaden. Wir müssen uns um Speicherlecks kümmern. Natürlich können wir sehr gut unnötige Teile des Codes zur Laufzeit zerstören und so Speicher freigeben, der in unserem Lebenszyklus nicht mehr verwendet wird. Darüber hinaus müssen wir alle Möglichkeiten der Schaffung temporärer Paradoxe in den Ketten von Prototypen beseitigen, da es in der Tat recht einfach ist, den Vorfahren von seinem eigenen Nachkommen zu erben. Dies kann jedoch bereits sehr gefährlich sein, da solche Techniken des Flirtens mit der Vergangenheit aus der Zukunft ganze Haufen von Heisenbags erzeugen können, die schwer zu reproduzieren sind, insbesondere wenn wir versuchen, etwas zu messen, das sich im Laufe der Zeit selbst ändern kann.

Chronik der Entscheidungen


Lassen Sie es einfach, offensichtlich und nicht sehr nützlich sein, aber anstatt an unseren Designer und ParentObject als Mama und Papa zu denken, beschreiben wir sie als Ei und ... Pollen . Wenn wir dann in Zukunft die Zygote mit dem geschätzten Wort " neu " erstellen, wird dies unserer Vorstellungskraft keinen Schaden mehr zufügen!

In dem Moment, in dem wir dies tun, werden wir alle drei oben genannten Probleme sofort beseitigen! Dazu brauchen wir natürlich die Fähigkeit, die Zygoten selbst zu erstellen, was bedeutet, dass wir die Fabrik der Designer brauchen. Und jetzt nenn es so, wie du willst, Mütter, Väter, was ist der Unterschied, denn unter dem Strich müssen wir, wenn wir " neu " sagen wollen, einen "brandneuen" Blumen-Designer-Käfig schaffen, Pollen darauf setzen und nur das wird uns erlauben ein neues „richtiges“ Schneeglöckchen im fernen und so schneebedeckten 2020m wachsen zu lassen:

 var Pollen = { season : 'Spring' }; // factory of constructors var FlowersFactory = function (proto) { var FlowerEggCell = function (sort) { this.sort = sort; }; FlowerEggCell.prototype = proto; return FlowerEggCell; }; var FlowerZygote = FlowersFactory(Pollen); var galanthus = new FlowerZygote('Galanthus'); 

(Und ja, vergessen Sie nicht, die Jahreszeit mit diesem Schneeglöckchen zu überprüfen, da sonst Schneeflocken fallen oder fallen und ein Schneeglöckchen eine Frühlingsblume wäre ...)

Natürlich ist die zyklomatische Komplexität der Entscheidungen, die Sie mit diesem Ansatz treffen möchten, mit dem Rätsel vergleichbar Einstein . Deshalb bin ich hier „auf dem Knie“ zusammengebraut bibliotechku , kann es mit der Schaffung helfen Ketten von Designern und memoization (ca. Hrsg . :. Nun, takoe, nehmen Sie die Pastetchen aus den Regalen, bla-bla-bla ) ...

Und obwohl ich es nicht beweisen kann, wird dieser Ansatz seit zwei Jahrzehnten von Zeit zu Zeit recht erfolgreich angewendet, wenn Sie 146% sicher sein müssen, dass bei der Vererbung alles normal ist. Sie können leicht selbst sehen, dass es elementar getestet, reproduziert und unterstützt wird (Anmerkung der Redaktion : Ja, im Moment haben Sie alles verlassen und sind gegangen, um sicherzugehen ).

Natürlich ist dies nicht die ganze Geschichte, wir haben lediglich die Tatsache festgestellt: JavaScript ist gut genug entworfen, um das Genealogie-Diagramm direkt durch Vererbung zu beschreiben. Natürlich haben wir hier nicht ein schlauen Themen berühren Die Klasse Abbau, aber ich bin sicher , dass Sie sich leicht ersetzen können FlowerEggCell auf FlowerEggCellClass innerhalb FlowersFactory: Die Essenz bleibt dieselbe, wenn Sie Ihre Blumen anhand einer Instanz überprüfen möchten , bei der Sie feststellen , dass sie alle Nachkommen von FlowerEggCell sind, auf die Sie über FlowerZygote verweisen . Und jetzt können Sie natürlich die Eigenschaften von FlowerZygote selbst ändern , da dies FlowersFactory selbst keinen Schaden zufügt . Es kann auch in Zukunft andere neue FlowerEggCell- oder FlowerEggCellClass-Konstruktoren gemäß dem ursprünglichen " Referenz " -Design erstellen, das Sie dort angegeben haben.

Ich hoffe, dieser Artikel hat alle Zweifel an der Wichtigkeit des Wortes .prototype zerstreut, wenn Sie das nächste Mal null sehen this , . call (null , . apply (null . bind (null code style (. .: Sorrow , , , ).

!

!

V

Source: https://habr.com/ru/post/de470994/


All Articles