Jestem przyzwyczajony do klasycznego OOP, jak w Javie.
Jakie są najlepsze praktyki wykonywania OOP w JavaScript przy użyciu NodeJS?
Każda klasa to plik z module.export
?
Jak tworzyć klasy?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
vs. (nie jestem nawet pewien, czy to prawda)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
vs.
this.Class = function() {}
this.Class.prototype.method = function(){}
...
Jak działałoby dziedziczenie?
Czy istnieją specjalne moduły do implementacji OOP w NodeJS?
Znajduję tysiące różnych sposobów tworzenia rzeczy, które przypominają OOP ... ale nie mam pojęcia, jaki jest najczęściej używany / praktyczny / czysty sposób.
Pytanie dodatkowe : jaki jest sugerowany „styl OOP” do użycia z MongooseJS? (czy dokument MongooseJS może być postrzegany jako klasa i model używany jako instancja?)
EDYTOWAĆ
tutaj jest przykład w JsFiddle prosimy o przesłanie opinii.
//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
łańcucha . I nie, obiekt nie obsługuje członków „ prywatnych ”. Tylko zamknięcia mogą to zaoferować, chociaż moduły / skrypty w Node.js są zaimplementowane jako zamknięcia.Odpowiedzi:
To jest przykład, który działa po wyjęciu z pudełka. Jeśli chcesz mniej "hacków", powinieneś użyć biblioteki dziedziczenia lub czegoś podobnego.
Cóż, w pliku animal.js napisałbyś:
Aby użyć go w innym pliku:
Jeśli chcesz mieć „podklasę”, to wewnątrz mouse.js:
Zamiast dziedziczenia wertykalnego można również rozważyć opcję „Pożyczanie metod”. Nie musisz dziedziczyć po „klasie”, aby użyć jej metody w swojej klasie. Na przykład:
źródło
Animal.prototype.getAge= function(){}
a zwykłym dodawaniem dothis.getAge = function(){}
środkafunction Animal() {}
?inherits
Podklasa wydaje się trochę zepsuta… z biblioteką „dziedziczenia” masz na myśli coś takiego, jak sugeruje @badsyntax?inherits(Mouse, Animal);
co trochę wyczyści konfigurację dziedziczenia. Różnica polega na tym, że tworzysz nową tożsamość funkcji dla każdego tworzonego obiektu zamiast współużytkowania jednej funkcji. Jeśli masz 10 myszy, utworzyłeś 10 tożsamości funkcji (to tylko dlatego, że mysz ma jedną metodę, gdyby miała 10 metod, 10 myszy utworzyłoby 100 tożsamości funkcji, twój serwer szybko zmarnuje większość swojego procesora na GC: P) , nawet jeśli nie będziesz ich używać do niczego. Język nie ma obecnie wystarczającej siły wyrazu, aby to zoptymalizować.Mouse.prototype = new Animal()
.. jak to się ma do twojego przykładu? (np. co to jestObject.create()
?)Ponieważ społeczność Node.js zapewnia, że nowe funkcje ze specyfikacji JavaScript ECMA-262 zostaną dostarczone programistom Node.js. w odpowiednim czasie.
Możesz przyjrzeć się klasom JavaScript . Łącze w MDN do klas JS W klasach JavaScript ECMAScript 6 jest wprowadzonych, ta metoda zapewnia łatwiejszy sposób modelowania koncepcji OOP w JavaScript.
Uwaga : klasy JS będą działać tylko w trybie ścisłym .
Poniżej znajduje się szkielet klasy, dziedziczenie napisane w Node.js (używana wersja Node.js v5.0.0 )
Deklaracje klas:
Dziedziczenie:
źródło
Sugeruję użycie
inherits
pomocnika, który jest dostarczany ze standardowymutil
modułem: http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructorJest przykład, jak go używać na połączonej stronie.
źródło
Oto najlepszy film o JavaScript zorientowanym obiektowo w Internecie:
Ostateczny przewodnik po JavaScript zorientowanym obiektowo
Oglądaj od początku do końca !!
Zasadniczo Javascript jest językiem opartym na prototypie, który różni się znacznie od klas w Javie, C ++, C # i innych popularnych znajomych. Film wyjaśnia podstawowe pojęcia o wiele lepiej niż jakakolwiek odpowiedź tutaj.
W ES6 (wydanym 2015) otrzymaliśmy słowo kluczowe „class”, które pozwala nam używać „klas” Javascript, tak jak w przypadku Java, C ++, C #, Swift itp.
Zrzut ekranu z wideo pokazujący, jak napisać i utworzyć instancję klasy / podklasy Javascript:
źródło
W społeczności Javascript wiele osób twierdzi, że OOP nie powinno być używane, ponieważ model prototypowy nie pozwala na natywne wykonanie ścisłego i niezawodnego OOP. Jednak nie uważam, że OOP jest kwestią języka, ale raczej kwestią architektury.
Jeśli chcesz użyć naprawdę mocnego OOP w Javascript / Node, możesz rzucić okiem na pełną platformę open source Danf . Zapewnia wszystkie potrzebne funkcje dla silnego kodu OOP (klasy, interfejsy, dziedziczenie, iniekcję zależności, ...). Pozwala także na używanie tych samych klas zarówno po stronie serwera (węzła), jak i klienta (przeglądarki). Co więcej, możesz kodować własne moduły danf i dzielić się nimi z każdym dzięki Npm.
źródło
Jeśli pracujesz na własną rękę i chcesz, aby było to jak najbardziej zbliżone do OOP, tak jak w Javie, C # lub C ++, zajrzyj do biblioteki javascript CrxOop. CrxOop zapewnia składnię nieco znaną programistom Java.
Tylko uważaj, OOP Java to nie to samo, co w Javascript. Aby uzyskać to samo zachowanie, co w Javie, użyj klas CrxOop, a nie struktur CrxOop i upewnij się, że wszystkie metody są wirtualne. Przykładem składni jest:
Kod jest w czystym javascript, bez transpilacji. Przykład zaczerpnięto z szeregu przykładów z oficjalnej dokumentacji.
źródło