Ich bin an die klassische OOP wie in Java gewöhnt.
Was sind die Best Practices für OOP in JavaScript mit NodeJS?
Jede Klasse ist eine Datei mit module.export
?
Wie erstelle ich Klassen?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
(Ich bin mir nicht mal sicher, ob es richtig ist)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
vs.
this.Class = function() {}
this.Class.prototype.method = function(){}
...
Wie würde die Vererbung funktionieren?
Gibt es spezielle Module zur Implementierung von OOP in NodeJS?
Ich finde tausend verschiedene Wege, um Dinge zu erschaffen, die OOP ähneln. Aber ich habe keine Ahnung, was der am häufigsten verwendete / praktische / saubere Weg ist.
Bonusfrage : Was ist der empfohlene "OOP-Stil" für MongooseJS? (Kann ein MongooseJS-Dokument als Klasse und als Modell als Instanz verwendet werden?)
BEARBEITEN
Hier ist ein Beispiel in JsFiddle. Bitte geben Sie Feedback.
//http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/
function inheritPrototype(childObject, parentObject) {
var copyOfParent = Object.create(parentObject.prototype)
copyOfParent.constructor = childObject
childObject.prototype = copyOfParent
}
//example
function Canvas (id) {
this.id = id
this.shapes = {} //instead of array?
console.log("Canvas constructor called "+id)
}
Canvas.prototype = {
constructor: Canvas
, getId: function() {
return this.id
}
, getShape: function(shapeId) {
return this.shapes[shapeId]
}
, getShapes: function() {
return this.shapes
}
, addShape: function (shape) {
this.shapes[shape.getId()] = shape
}
, removeShape: function (shapeId) {
var shape = this.shapes[shapeId]
if (shape)
delete this.shapes[shapeId]
return shape
}
}
function Shape(id) {
this.id = id
this.size = { width: 0, height: 0 }
console.log("Shape constructor called "+id)
}
Shape.prototype = {
constructor: Shape
, getId: function() {
return this.id
}
, getSize: function() {
return this.size
}
, setSize: function (size) {
this.size = size
}
}
//inheritance
function Square(id, otherSuff) {
Shape.call(this, id) //same as Shape.prototype.constructor.apply( this, arguments ); ?
this.stuff = otherSuff
console.log("Square constructor called "+id)
}
inheritPrototype(Square, Shape)
Square.prototype.getSize = function() { //override
return this.size.width
}
function ComplexShape(id) {
Shape.call(this, id)
this.frame = null
console.log("ComplexShape constructor called "+id)
}
inheritPrototype(ComplexShape, Shape)
ComplexShape.prototype.getFrame = function() {
return this.frame
}
ComplexShape.prototype.setFrame = function(frame) {
this.frame = frame
}
function Frame(id) {
this.id = id
this.length = 0
}
Frame.prototype = {
constructor: Frame
, getId: function() {
return this.id
}
, getLength: function() {
return this.length
}
, setLength: function (length) {
this.length = length
}
}
/////run
var aCanvas = new Canvas("c1")
var anotherCanvas = new Canvas("c2")
console.log("aCanvas: "+ aCanvas.getId())
var aSquare = new Square("s1", {})
aSquare.setSize({ width: 100, height: 100})
console.log("square overridden size: "+aSquare.getSize())
var aComplexShape = new ComplexShape("supercomplex")
var aFrame = new Frame("f1")
aComplexShape.setFrame(aFrame)
console.log(aComplexShape.getFrame())
aCanvas.addShape(aSquare)
aCanvas.addShape(aComplexShape)
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
anotherCanvas.addShape(aCanvas.removeShape("supercomplex"))
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
console.log("Shapes in anotherCanvas: "+Object.keys(anotherCanvas.getShapes()).length)
console.log(aSquare instanceof Shape)
console.log(aComplexShape instanceof Shape)
prototype
Kette . Und nein, Objekt unterstützt keine " privaten " Mitglieder. Dies können nur Closures bieten, obwohl Module / Skripte in Node.js als Closures implementiert sind.Antworten:
Dies ist ein Beispiel, das sofort funktioniert. Wenn Sie weniger "hacky" wollen, sollten Sie eine Vererbungsbibliothek oder ähnliches verwenden.
Nun, in eine Datei animal.js würden Sie schreiben:
So verwenden Sie es in einer anderen Datei:
Wenn Sie eine "Unterklasse" möchten, dann in mouse.js:
Sie können auch "Methodenausleihe" anstelle der vertikalen Vererbung in Betracht ziehen. Sie müssen nicht von einer "Klasse" erben, um ihre Methode für Ihre Klasse zu verwenden. Zum Beispiel:
quelle
Animal.prototype.getAge= function(){}
und dem einfachen Hinzufügen imthis.getAge = function(){}
Innerenfunction Animal() {}
? Die Unterklasse scheint ein bisschen hackig zu sein. Mit "Vererbungs" -Bibliothek meinen Sie so etwas wieinherits
von @badsyntax vorgeschlagen?inherits(Mouse, Animal);
, um die Vererbung ein wenig zu bereinigen. Der Unterschied besteht darin, dass Sie für jedes instanziierte Objekt eine neue Funktionsidentität erstellen, anstatt eine Funktion gemeinsam zu nutzen. Wenn Sie 10 Mäuse haben, haben Sie 10 Funktionsidentitäten erstellt (das liegt nur daran, dass die Maus eine Methode hat. Wenn sie 10 Methoden hätte, würden 10 Mäuse 100 Funktionsidentitäten erstellen, würde Ihr Server schnell den größten Teil seiner CPU auf GC: P verschwenden.) , obwohl Sie sie für nichts verwenden werden. Die Sprache hat derzeit nicht genug Ausdruckskraft, um dies zu optimieren.Mouse.prototype = new Animal()
.. wie ist es mit Ihrem Beispiel zu vergleichen? (zB was istObject.create()
?)Da die Node.js-Community sicherstellt, dass neue Funktionen aus der JavaScript ECMA-262-Spezifikation den Entwicklern von Node.js rechtzeitig zur Verfügung gestellt werden.
Sie können sich JavaScript-Klassen ansehen . MDN-Link zu JS-Klassen In der Einführung von JavaScript-Klassen in ECMAScript 6 bietet diese Methode eine einfachere Möglichkeit, OOP-Konzepte in Javascript zu modellieren.
Hinweis : JS-Klassen funktionieren nur im strengen Modus .
Unten finden Sie ein Skelett der Klasse, Vererbung in Node.js (Used Node.js Version v5.0.0 )
Klassenerklärungen:
Vererbung:
quelle
Ich schlage vor, den
inherits
mit dem Standardmodul gelieferten Helfer zu verwendenutil
: http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructorAuf der verlinkten Seite finden Sie ein Beispiel für die Verwendung.
quelle
Dies ist das beste Video über objektorientiertes JavaScript im Internet:
Der endgültige Leitfaden für objektorientiertes JavaScript
Beobachten Sie von Anfang bis Ende!
Grundsätzlich ist Javascript eine Prototyp-basierte Sprache, die sich deutlich von den Klassen in Java, C ++, C # und anderen beliebten Freunden unterscheidet. Das Video erklärt die Kernkonzepte weitaus besser als jede Antwort hier.
Mit ES6 (veröffentlicht 2015) haben wir ein Schlüsselwort "class" erhalten, mit dem wir Javascript-Klassen wie mit Java, C ++, C #, Swift usw. verwenden können.
Screenshot aus dem Video, der zeigt, wie eine Javascript-Klasse / Unterklasse geschrieben und instanziiert wird:
quelle
In der Javascript-Community argumentieren viele Leute, dass OOP nicht verwendet werden sollte, da das Prototypmodell keine strenge und robuste OOP nativ zulässt. Ich denke jedoch nicht, dass OOP eine Frage der Sprache ist, sondern eher eine Frage der Architektur.
Wenn Sie eine wirklich starke OOP in Javascript / Node verwenden möchten, können Sie sich das Full-Stack-Open-Source-Framework Danf ansehen . Es bietet alle erforderlichen Funktionen für einen starken OOP-Code (Klassen, Schnittstellen, Vererbung, Abhängigkeitsinjektion, ...). Außerdem können Sie auf der Server- (Knoten-) und der Client- (Browser-) Seite dieselben Klassen verwenden. Darüber hinaus können Sie Ihre eigenen Danf-Module codieren und dank Npm mit anderen teilen.
quelle
Wenn Sie alleine arbeiten und OOP am nächsten kommen möchten, wie Sie es in Java, C # oder C ++ finden würden, lesen Sie die Javascript-Bibliothek CrxOop. CrxOop bietet eine Syntax, die Java-Entwicklern vertraut ist.
Seien Sie vorsichtig, Javas OOP ist nicht dasselbe wie das in Javascript. Verwenden Sie die CrxOop-Klassen und nicht die CrxOop-Strukturen, um dasselbe Verhalten wie in Java zu erzielen, und stellen Sie sicher, dass alle Ihre Methoden virtuell sind. Ein Beispiel für die Syntax ist:
Der Code ist reines Javascript, kein Transpilieren. Das Beispiel stammt aus einer Reihe von Beispielen aus der offiziellen Dokumentation.
quelle