Я привык к классическому ООП, как в Java.
Каковы лучшие практики для ООП в JavaScript с использованием NodeJS?
Каждый класс - это файл с module.export
?
Как создавать классы?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
vs. (даже не уверен, что это правильно)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
против
this.Class = function() {}
this.Class.prototype.method = function(){}
...
Как будет работать наследование?
Существуют ли специальные модули для реализации ООП в NodeJS?
Я нахожу тысячу различных способов создавать вещи, похожие на ООП ... но я понятия не имею, какой из них наиболее используемый / практичный / чистый.
Дополнительный вопрос : какой предлагаемый «стиль ООП» использовать с MongooseJS? (можно ли рассматривать документ MongooseJS как класс, а модель как экземпляр?)
РЕДАКТИРОВАТЬ
вот пример в JsFiddle, пожалуйста, оставьте отзыв.
//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
цепочке . И нет, объект не поддерживает " закрытые " члены. Это могут предложить только замыкания , хотя модули / скрипты в Node.js реализованы как замыкания.Ответы:
Это пример, который работает "из коробки". Если вы хотите меньше «хакерства», вам следует использовать библиотеку наследования или что-то подобное.
В файле animal.js вы должны написать:
Чтобы использовать его в другом файле:
Если вам нужен «подкласс», то внутри mouse.js:
Также вы можете рассмотреть «Заимствование метода» вместо вертикального наследования. Вам не нужно наследовать от «класса», чтобы использовать его метод в своем классе. Например:
источник
Animal.prototype.getAge= function(){}
и простым добавлениемthis.getAge = function(){}
внутрьfunction Animal() {}
?inherits
Подкласс кажется немного взломанным ... с библиотекой "наследования" вы имеете в виду что-то вроде того, что предлагает @badsyntax?inherits(Mouse, Animal);
чтобы немного очистить настройку наследования. Разница в том, что вы создаете новый идентификатор функции для каждого экземпляра объекта вместо совместного использования одной функции. Если у вас 10 мышей, вы создали 10 идентификаторов функций (это только потому, что у мыши есть один метод, если бы у него было 10 методов, 10 мышей создали бы 100 идентификаторов функций, ваш сервер быстро потратил бы большую часть своего процессора на GC: P) , даже если вы ни для чего не будете их использовать. У языка недостаточно выразительной силы, чтобы оптимизировать это в настоящее время.Mouse.prototype = new Animal()
.. как это соотносится с вашим примером? (например, что такоеObject.create()
?)Поскольку сообщество Node.js гарантирует, что новые функции из спецификации JavaScript ECMA-262 будут своевременно представлены разработчикам Node.js.
Вы можете взглянуть на классы JavaScript . Ссылка MDN на классы JS В классах JavaScript ECMAScript 6 этот метод обеспечивает более простой способ моделирования концепций ООП в Javascript.
Примечание : классы JS будут работать только в строгом режиме .
Ниже представлен скелет класса, наследование написано на Node.js (Используемая версия Node.js v5.0.0 )
Объявления классов:
Наследование:
источник
Я предлагаю использовать
inherits
помощник, который поставляется со стандартнымutil
модулем: http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructorВот пример того, как использовать его на связанной странице.
источник
Это лучший видеоролик об объектно-ориентированном JavaScript в Интернете:
Полное руководство по объектно-ориентированному JavaScript
Смотрите от начала до конца !!
По сути, Javascript - это язык, основанный на прототипах, который сильно отличается от классов в Java, C ++, C # и других популярных языках. Видео объясняет основные концепции намного лучше, чем любой ответ здесь.
В ES6 (выпущенном в 2015 г.) мы получили ключевое слово «class», которое позволяет нам использовать «классы» Javascript, как в случае с Java, C ++, C #, Swift и т. Д.
Снимок экрана из видео, показывающий, как написать и создать экземпляр класса / подкласса Javascript:
источник
В сообществе Javascript многие люди утверждают, что ООП не следует использовать, потому что модель прототипа не позволяет выполнять строгое и надежное ООП изначально. Однако я не думаю, что ООП - это вопрос языка, а скорее вопрос архитектуры.
Если вы хотите использовать действительно сильное ООП в Javascript / Node, вы можете взглянуть на полнофункциональный фреймворк с открытым исходным кодом Danf . Он предоставляет все необходимые функции для сильного ООП-кода (классы, интерфейсы, наследование, внедрение зависимостей, ...). Он также позволяет использовать одни и те же классы как на стороне сервера (узла), так и на стороне клиента (браузера). Более того, вы можете кодировать свои собственные модули danf и делиться ими с кем угодно благодаря Npm.
источник
Если вы работаете самостоятельно и хотите, чтобы ООП было максимально приближено к Java, C # или C ++, см. Библиотеку javascript CrxOop. CrxOop предоставляет синтаксис, несколько знакомый разработчикам Java.
Только будьте осторожны, ООП в Java отличается от ООП в Javascript. Чтобы добиться того же поведения, что и в Java, используйте классы CrxOop, а не структуры CrxOop, и убедитесь, что все ваши методы виртуальны. Пример синтаксиса:
Код представляет собой чистый javascript, без транспиляции. Пример взят из ряда примеров из официальной документации.
источник