Estou acostumado com o OOP clássico como em Java.
Quais são as melhores práticas para fazer OOP em JavaScript usando NodeJS?
Cada classe é um arquivo com module.export
?
Como criar classes?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
vs. (nem tenho certeza se está correto)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
vs.
this.Class = function() {}
this.Class.prototype.method = function(){}
...
Como funcionaria a herança?
Existem módulos específicos para implementar OOP em NodeJS?
Estou descobrindo milhares de maneiras diferentes de criar coisas que se assemelham ao OOP ... mas não tenho ideia de qual é a maneira mais usada / prática / limpa.
Pergunta bônus : qual é o "estilo OOP" sugerido para usar com o MongooseJS? (pode um documento MongooseJS ser visto como uma classe e um modelo usado como uma instância?)
EDITAR
aqui está um exemplo em JsFiddle , forneça 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)
javascript
node.js
oop
inheritance
mongoose
fusio
fonte
fonte
prototype
cadeia . E, não, o objeto não oferece suporte a membros " privados ". Apenas os fechamentos podem oferecer isso, embora os módulos / scripts em Node.js sejam implementados como fechamentos.Respostas:
Este é um exemplo que funciona fora da caixa. Se você quiser menos "hacky", deve usar uma biblioteca de herança ou algo parecido.
Bem, em um arquivo animal.js você escreveria:
Para usá-lo em outro arquivo:
Se você quiser uma "subclasse", dentro de mouse.js:
Além disso, você pode considerar "empréstimo de método" em vez de herança vertical. Você não precisa herdar de uma "classe" para usar seu método em sua classe. Por exemplo:
fonte
Animal.prototype.getAge= function(){}
e simplesmente adicionarthis.getAge = function(){}
dentrofunction Animal() {}
? A subclasse parece um pouco hackeada .. com biblioteca de "herança" você quer dizer algo comoinherits
sugerido por @badsyntax?inherits(Mouse, Animal);
limpar um pouco a configuração de herança. A diferença é que você está criando uma nova identidade de função para cada objeto instanciado em vez de compartilhar uma função. Se você tiver 10 mouses, terá criado 10 identidades de função (isso é apenas porque o mouse tem um método, se tivesse 10 métodos, 10 mouses criariam 100 identidades de função, seu servidor rapidamente desperdiçaria a maior parte de sua CPU em GC: P) , mesmo que você não os use para nada. A linguagem não tem poder expressivo suficiente para otimizar isso atualmente.Mouse.prototype = new Animal()
.. como isso se compara ao seu exemplo? (por exemplo, o que éObject.create()
?)Como a comunidade Node.js garante que novos recursos da especificação JavaScript ECMA-262 sejam trazidos aos desenvolvedores Node.js em tempo hábil.
Você pode dar uma olhada nas classes JavaScript . Link MDN para classes JS Nas classes ECMAScript 6 JavaScript são introduzidas, este método fornece uma maneira mais fácil de modelar conceitos OOP em Javascript.
Nota : as classes JS funcionarão apenas no modo estrito .
Abaixo está algum esqueleto de classe, herança escrita em Node.js (versão Node.js usada v5.0.0 )
Declarações de classe:
Herança:
fonte
Sugiro usar o
inherits
auxiliar que vem com outil
módulo padrão : http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructorHá um exemplo de como usá-lo na página vinculada.
fonte
Este é o melhor vídeo sobre JavaScript orientado a objetos na Internet:
O guia definitivo para JavaScript orientado a objetos
Assista do começo ao fim !!
Basicamente, Javascript é uma linguagem baseada em protótipo que é bastante diferente das classes em Java, C ++, C # e outros amigos populares. O vídeo explica os conceitos básicos muito melhor do que qualquer resposta aqui.
Com o ES6 (lançado em 2015), obtivemos uma palavra-chave "class" que nos permite usar "classes" Javascript como faríamos com Java, C ++, C #, Swift, etc.
Captura de tela do vídeo mostrando como escrever e instanciar uma classe / subclasse Javascript:
fonte
Na comunidade Javascript, muitas pessoas argumentam que OOP não deve ser usado porque o modelo de protótipo não permite fazer um OOP rígido e robusto nativamente. No entanto, não acho que OOP seja uma questão de linguagem, mas sim uma questão de arquitetura.
Se você deseja usar um OOP realmente forte em Javascript / Node, pode dar uma olhada no framework de código aberto Danf full stack . Ele fornece todos os recursos necessários para um código OOP forte (classes, interfaces, herança, injeção de dependência, ...). Ele também permite que você use as mesmas classes nos lados do servidor (nó) e do cliente (navegador). Além disso, você pode codificar seus próprios módulos danf e compartilhá-los com qualquer pessoa, graças ao Npm.
fonte
Se você está trabalhando por conta própria e deseja a coisa mais próxima de OOP como encontraria em Java, C # ou C ++, consulte a biblioteca javascript, CrxOop. CrxOop fornece sintaxe um tanto familiar para desenvolvedores Java.
Apenas tome cuidado, a OOP do Java não é a mesma encontrada no Javascript. Para obter o mesmo comportamento do Java, use as classes do CrxOop, não as estruturas do CrxOop, e certifique-se de que todos os seus métodos sejam virtuais. Um exemplo da sintaxe é,
O código é javascript puro, sem transpilar. O exemplo é retirado de vários exemplos da documentação oficial.
fonte