Ich wandle mich gerade von Java zu Javascript um, und es fällt mir ein bisschen schwer, herauszufinden, wie ich Objekte so erweitern kann, wie ich es möchte.
Ich habe mehrere Leute im Internet gesehen, die eine Methode namens "Erweitern auf Objekt" verwenden. Der Code sieht folgendermaßen aus:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Weiß jemand, wie man diese Arbeit macht? Ich habe gehört, dass Sie schreiben müssen
Object.prototype.extend = function(...);
Aber ich weiß nicht, wie ich dieses System zum Laufen bringen soll. Wenn dies nicht möglich ist, zeigen Sie mir bitte eine andere Alternative, die ein Objekt erweitert.
extend
Funktion sind, habe ich hier ein Beispiel erstellt: jsfiddle.net/k9LRdAntworten:
Sie möchten vom Prototypobjekt der Person "erben":
quelle
Person()
Konstruktor aufgerufen, wenn Sie dies tunnew Robot()
? Es scheint mir, dass Sie diesen Basisklassenkonstruktor aufrufen sollten, anstatt ihnthis.name = name;
imRobot()
Konstruktor zu tun ...Person.apply(this, arguments);
. Es wäre auch besser,Robot.prototype = Object.create(Person.prototype);
statt zu verwendennew Person();
.Welt ohne das "neue" Schlüsselwort.
Und einfachere "prosaähnliche" Syntax mit Object.create ().
* Dieses Beispiel wurde für ES6-Klassen aktualisiert.
Denken Sie zunächst daran, dass Javascript eine prototypische Sprache ist . Es ist nicht klassenbasiert. Daher enthüllt das Schreiben in prototypischer Form seine wahre Natur und kann sehr einfach, prosaartig und kraftvoll sein.
TLDR;
Nein, Sie brauchen keine Konstruktoren, keine
new
Instanziierung ( lesen Sie, warum Sie sie nicht verwenden solltennew
), neinsuper
, kein lustiger Witz__construct
. Sie erstellen einfach Objekte und erweitern oder verwandeln sie dann.( Wenn Sie sich mit Gettern und Setzern auskennen, lesen Sie den Abschnitt "Weiterführende Literatur", um zu erfahren, wie Sie mit diesem Muster kostenlose Getter und Setter erhalten, wie Javascript es ursprünglich beabsichtigt hatte, und wie leistungsfähig sie sind .)
Prosaähnliche Syntax: Basisprototyp
Sieht auf einen Blick gut lesbar aus.
Erweiterung, die einen Nachkommen von erstellt
Person
* Die richtigen Begriffe sind
prototypes
und ihredescendants
. Es gibt keineclasses
und keine Notwendigkeit fürinstances
.Eine Möglichkeit, eine "Standard" -Methode zum Erstellen eines zu erstellen
descendant
, besteht darin, eine#create
Methode anzuhängen :Die folgenden Möglichkeiten haben eine geringere Lesbarkeit:
Vergleichen Sie mit dem "klassischen" Äquivalent:
Die Lesbarkeit des Codes im "klassischen" Stil ist nicht so gut.
ES6-Klassen
Zugegeben, einige dieser Probleme werden von den ES6-Klassen beseitigt, aber dennoch:
Verzweigung des Basisprototyps
Fügen Sie Methoden hinzu, die für
Robot
Vererbung überprüfen
Sie haben schon alles, was Sie brauchen! Keine Konstruktoren, keine Instanziierung. Saubere, klare Prosa.
Weiterführende Literatur
Beschreibbarkeit, Konfigurierbarkeit und kostenlose Getter und Setter!
Für kostenlose Getter und Setter oder zusätzliche Konfigurationen können Sie das zweite Argument von Object.create () verwenden, auch bekannt als propertiesObject. Es ist auch in # Object.defineProperty und # Object.defineProperties verfügbar .
Um zu veranschaulichen, wie mächtig dies ist, möchten wir, dass alle
Robot
streng aus Metall (viawritable: false
) bestehen undpowerConsumption
Werte standardisieren (via Getter und Setter).Und alle Prototypen von
Robot
können nichtmadeOf
etwas anderes sein, weilwritable: false
.Mixins (mit # Object.assign) - Anakin Skywalker
Kannst du spüren, wohin das führt ...?
Darth Vader erhält die Methoden von
Robot
:Zusammen mit anderen seltsamen Dingen:
Nun, ob Darth Vader Mensch oder Maschine ist, ist in der Tat subjektiv:
Extra - Etwas kürzere Syntax mit # Object.assign
Höchstwahrscheinlich verkürzt dieses Muster Ihre Syntax. ES6 # Object.assign kann sich jedoch noch etwas verkürzen (Informationen zur Verwendung von Polyfill in älteren Browsern finden Sie unter MDN in ES6 ).
quelle
Object.assign(Robot, {a:1}
eine gute Alternative für Ihreextend()
Methode? 2) Wie überschreibe ich diegreet()
Methode, damit sie denselben Text zurückgibt, aber eine "Begrüßungsüberschreibung" angehängt ist?#Object.assign
sieht aus wie eine gute Alternative. Die Browserunterstützung ist jedoch geringer. 2) Sie verwenden die__proto__
Eigenschaft des Objekts, um auf die Begrüßungsfunktion des Prototyps zuzugreifen. Anschließend rufen Sie die Begrüßungsfunktion des Prototyps mit dem übergebenen Bereich des Angerufenen auf. In diesem Fall war die Funktion ein Konsolenprotokoll, sodass kein "Anhängen" möglich ist. Aber mit diesem Beispiel denke ich, dass Sie die Drift bekommen.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Wenn Sie noch keinen Weg gefunden haben, verwenden Sie die assoziative Eigenschaft von JavaScript-Objekten, um der
Object.prototype
unten gezeigten Funktion eine Erweiterungsfunktion hinzuzufügen .Sie können diese Funktion dann wie unten gezeigt verwenden.
quelle
Anderer Ansatz: Object.create
Per @ osahyoun-Antwort finde ich Folgendes als eine bessere und effizientere Möglichkeit, vom Prototypobjekt einer Person zu "erben":
Neue Instanzen erstellen:
Verwenden Sie jetzt Object.create :
Überprüfen Sie auch die MDN- Dokumentation.
quelle
name
Parameter nicht wie folgt an den übergeordneten Konstruktor: jsfiddle.net/3brm0a7a/3 (Unterschied ist in Zeile 8)In ES6 können Sie Spread-Operatoren wie verwenden
Weitere Informationen finden Sie unter dem Link MDN-Spread-Syntax
Alte Antwort:
In ES6 gibt es
Object.assign
zum Kopieren von Eigenschaftswerten. Verwendung{}
als erster param , wenn Sie nicht das Zielobjekt (das erste param bestanden) ändern mögen.Weitere Details finden Sie unter Link, MDN - Object.assign ()
Falls Sie eine Polyfill für ES5 benötigen , bietet der Link diese ebenfalls an. :) :)
quelle
Und ein weiteres Jahr später kann ich Ihnen sagen, dass es eine weitere nette Antwort gibt.
Wenn Ihnen die Funktionsweise des Prototyping zur Erweiterung von Objekten / Klassen nicht gefällt, lesen Sie Folgendes: https://github.com/haroldiedema/joii
Schneller Beispielcode für Möglichkeiten (und viele mehr):
quelle
Menschen, die immer noch um den einfachen und besten Ansatz kämpfen, können Sie
Spread Syntax
zum Erweitern von Objekten verwenden.Hinweis: Denken Sie daran, dass die am weitesten rechts liegende Eigenschaft Vorrang hat. In diesem Beispiel
person2
befindet sich auf der rechten Seite dernewObj
Name Robo .quelle
Möglicherweise möchten Sie eine Hilfsbibliothek wie underscore.js verwenden , deren eigene Implementierung von
extend()
.Und es ist auch eine gute Möglichkeit, anhand des Quellcodes zu lernen. Die kommentierte Quellcodepage ist sehr nützlich.
quelle
_.extend()
Arbeit von underscore.js seine Funktionalität deutlich macht: lostechies.com/chrismissal/2012/10/05/…Mozilla "kündigt" Objekt an, das sich von ECMAScript 6.0 erstreckt:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
HINWEIS: Dies ist eine experimentelle Technologie, die Teil des ECMAScript 6 (Harmony) -Vorschlags ist.
Diese Technologie ist in Gecko (Google Chrome / Firefox) verfügbar - 03/2015 Nightly Builds.
quelle
In den meisten Projekten gibt es eine Implementierung der Objekterweiterung: Unterstrich, Abfrage, Lodash: Erweitern .
Es gibt auch eine reine Javascript-Implementierung, die Teil von ECMAscript 6 ist: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
quelle
Dann:
Update 01/2017:
Bitte ignorieren Sie meine Antwort von 2015, da Javascript jetzt das
extends
Schlüsselwort seit ES6 unterstützt (Ecmasctipt6).- ES6:
- ES7:
quelle
new ParentClass()
vor dem Überschreiben des Konstruktors haben Sie den übergeordneten Konstruktor bereits ausgeführt. Ich denke nicht, dass das korrektes Verhalten ist, wenn Sie mich fragen ...Zusammenfassung:
Javascript verwendet einen Mechanismus, der als prototypische Vererbung bezeichnet wird . Die prototypische Vererbung wird verwendet, wenn eine Eigenschaft für ein Objekt gesucht wird. Wenn wir Eigenschaften in Javascript erweitern, erben wir diese Eigenschaften von einem tatsächlichen Objekt. Es funktioniert folgendermaßen:
myObj.foo
odermyObj['foo']
), sucht die JS-Engine zuerst nach dieser Eigenschaft im Objekt selbstWenn wir von einem Objekt in Javascript aus erweitern möchten, können wir dieses Objekt einfach in der Prototypenkette verknüpfen. Es gibt zahlreiche Möglichkeiten, dies zu erreichen. Ich werde zwei häufig verwendete Methoden beschreiben.
Beispiele:
1.
Object.create()
Object.create()
ist eine Funktion, die ein Objekt als Argument verwendet und ein neues Objekt erstellt. Das Objekt, das als Argument übergeben wurde, ist der Prototyp des neu erstellten Objekts. Beispielsweise:2. Explizites Festlegen der Prototyp-Eigenschaft
Beim Erstellen von Objekten mit Konstruktorfunktionen können wir festlegen, dass der Prototyp-Objekteigenschaft Eigenschaften hinzugefügt werden. Bei Objekten, die bei Verwendung des
new
Schlüsselworts eine Konstruktorfunktion bilden , wird der Prototyp auf den Prototyp der Konstruktorfunktion gesetzt. Beispielsweise:quelle
Sie können es einfach tun, indem Sie:
Dann benutze es wie folgt:
Dies führt zu:
quelle
BITTE GRUND FÜR DOWNVOTE HINZUFÜGEN
Zum Erweitern muss keine externe Bibliothek verwendet werden
In JavaScript ist alles ein Objekt (mit Ausnahme der drei primitiven Datentypen, und selbst sie werden bei Bedarf automatisch mit Objekten umbrochen). Darüber hinaus sind alle Objekte veränderlich.
Dank Ross Schaden, Dustin Diaz
quelle
Dadurch können Sie Ihre Eigenschaften erweitern und ein neues Objekt mit den Objektparameter-Prototypen erstellen, ohne das übergebene Objekt zu ändern.
Wenn Sie Ihr Objekt jedoch erweitern möchten, ohne die Parameter zu ändern, können Sie Ihrem Objekt expandProperty hinzufügen.
quelle
Prototyping ist ein guter Weg, aber Prototypen sind manchmal ziemlich gefährlich und können zu Fehlern führen. Ich ziehe es vor, dies in ein Basisobjekt zu kapseln, wie es Ember.js mit Ember.Object.extend und Ember.Object.reopen tut. Das ist viel sicherer zu bedienen.
Ich habe eine Übersicht darüber erstellt, wie Sie etwas Ähnliches wie Ember.Object einrichten würden.
Hier ist der Link: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
quelle
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
Was meinst du damit? Die Verwendung der Prototypenkette in JavaScript kann zu Fehlern führen. Es ist wie zu sagen, dass die Verwendung von Klassen unter Java zu Fehlern führen kann und absolut keinen Sinn ergibt.Object
des Prototyps zu allem eine nützliche Dienstprogrammfunktion hinzufügen , hat Ihre Funktion möglicherweise denselben Namen wie eine zukünftige JavaScript-Funktion und führt dazu, dass Ihr Code explodiert, wenn er in Zukunft ausgeführt wird. Angenommen, Sie haben einerepeat()
Funktion zu Instanzen hinzugefügtObject
und diese fürString
Instanzen aufgerufen und anschließend Ihre JavaScript-Laufzeit auf ES6 aktualisiert.prototype
Sprache - Funktion .