web-dev-qa-db-fra.com

JavaScript OOP dans NodeJS: comment?

Je suis habitué au OOPclassique _ comme en Java.

Quelles sont les meilleures pratiques pour faire OOP en JavaScript avec NodeJS?

Chaque classe est un fichier avec module.export?

Comment créer des classes?

this.Class = function() {
    //constructor?
    var privateField = ""
    this.publicField = ""
    var privateMethod = function() {}
    this.publicMethod = function() {} 
}

contre (je ne suis même pas sûr que c'est correct)

this.Class = {
    privateField: ""
    , privateMethod: function() {}

    , return {
        publicField: ""
        publicMethod: function() {}
    }
}

vs.

this.Class = function() {}

this.Class.prototype.method = function(){}

...

Comment fonctionnerait l'héritage?

Existe-t-il des modules spécifiques pour implémenter OOP dans NodeJS?

Je trouve mille façons différentes de créer des choses qui ressemblent à la programmation orientée objet. Mais je n'ai aucune idée de ce qui est le plus utilisé/pratique/propre.

Question bonus : quel est le "style de POO" suggéré à utiliser avec MongooseJS? (Un document MongooseJS peut-il être vu comme une classe et un modèle utilisé comme instance?)

EDIT

voici un exemple dans JsFiddle s'il vous plaît fournir des commentaires.

//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)
102
fusio

Ceci est un exemple qui fonctionne hors de la boîte. Si vous voulez moins "hacky", vous devriez utiliser la bibliothèque d'héritage ou autre.

Eh bien, dans un fichier animal.js, vous écririez:

var method = Animal.prototype;

function Animal(age) {
    this._age = age;
}

method.getAge = function() {
    return this._age;
};

module.exports = Animal;

Pour l'utiliser dans un autre fichier:

var Animal = require("./animal.js");

var john = new Animal(3);

Si vous voulez une "sous-classe" alors dans mouse.js:

var _super = require("./animal.js").prototype,
    method = Mouse.prototype = Object.create( _super );

method.constructor = Mouse;

function Mouse() {
    _super.constructor.apply( this, arguments );
}
//Pointless override to show super calls
//note that for performance (e.g. inlining the below is impossible)
//you should do
//method.$getAge = _super.getAge;
//and then use this.$getAge() instead of super()
method.getAge = function() {
    return _super.getAge.call(this);
};

module.exports = Mouse;

Aussi, vous pouvez envisager "Méthode d'emprunt" au lieu d'un héritage vertical. Vous n'avez pas besoin d'hériter d'une "classe" pour utiliser sa méthode sur votre classe. Par exemple:

 var method = List.prototype;
 function List() {

 }

 method.add = Array.prototype.Push;

 ...

 var a = new List();
 a.add(3);
 console.log(a[0]) //3;
111
Esailija

En tant que communauté Node.js, les nouvelles fonctionnalités de la spécification JavaScript ECMA-262 sont présentées rapidement aux développeurs de Node.js.

Vous pouvez consulter les classes JavaScript . lien MDN vers les classes JS Dans l'ECMAScript 6, les méthodes JavaScript sont introduites, cette méthode offre un moyen plus simple de modéliser les concepts OOP en Javascript.

Remarque : Les classes JS ne fonctionneront qu'en mode strict .

Vous trouverez ci-dessous un squelette de classe, l'héritage écrit dans Node.js (version utilisée de Node.js v5.0.0 ).

Déclarations de classe:

'use strict'; 
class Animal{

 constructor(name){
    this.name = name ;
 }

 print(){
    console.log('Name is :'+ this.name);
 }
}

var a1 = new Animal('Dog');

Héritage:

'use strict';
class Base{

 constructor(){
 }
 // methods definitions go here
}

class Child extends Base{
 // methods definitions go here
 print(){ 
 }
}

var childObj = new Child();
41
Piyush Sagar

Je suggère d'utiliser l'assistant inherits fourni avec le module standard util: http://nodejs.org/api/util.html#util_inherits_constructor_superconstructor

Vous trouverez un exemple d'utilisation à la page liée.

14
badsyntax

Voici la meilleure vidéo sur le JavaScript orienté objet sur Internet:

Le guide définitif pour JavaScript orienté objet

Regarder du début à la fin !!

Fondamentalement, Javascript est un langage basé sur un prototype qui est assez différent des classes de Java, C++, C # et d’autres amis populaires. La vidéo explique les concepts de base bien mieux que n'importe quelle réponse ici.

Avec ES6 (sortie en 2015), nous avons obtenu un mot clé "class" qui nous permet d'utiliser des "classes" en Javascript, comme nous le ferions avec Java, C++, C #, Swift, etc.

Capture d'écran de la vidéo montrant comment écrire et instancier une classe/sous-classe Javascript: enter image description here

9
etayluz

Dans la communauté Javascript, de nombreuses personnes soutiennent que OOP ne doit pas être utilisé car le prototype ne permet pas de faire un OOP natif robuste et robuste. Cependant, je ne pense pas que OOP soit une question de langage mais plutôt d'architecture.

Si vous voulez utiliser un OOP fort en Javascript/Node, vous pouvez jeter un coup d'œil au framework open-source full-stack Danf . Il fournit toutes les fonctionnalités nécessaires pour un code OOP fort (classes, interfaces, héritage, injection de dépendances, ...). Cela vous permet également d'utiliser les mêmes classes du côté serveur (nœud) et du côté client (navigateur). De plus, vous pouvez coder vos propres modules danf et les partager avec n’importe qui grâce à Npm.

4
Gnucki