JavaScript POO dans NodeJS: comment?

Je suis habitué à la POO classique comme en Java.

Quelles sont les meilleures pratiques pour faire de la POO en JavaScript en utilisant 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() {} 
}

Vs. (Je ne suis même pas sûr que ce soit 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 la POO dans NodeJS?

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

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

Modifier

Voici un exemple dans JsFiddle{[33] } veuillez 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)
91
demandé sur fusio 2013-08-12 17:20:53

5 réponses

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

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 à l'intérieur de la souris.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;

Vous pouvez également envisager "l'emprunt de méthode" au lieu de l'héritage vertical. Vous n'avez pas besoin d'hériter d'une "classe" pour l'utilisation de 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;
104
répondu Esailija 2013-08-12 13:32:35

Comme Nœud.la communauté js s'assure que les nouvelles fonctionnalités de la spécification JavaScript ECMA-262 sont apportées au nœud.développeurs js en temps opportun.

Vous pouvez jeter un oeil à classes JavaScript. lien MDN vers les classes JS Dans L'ECMAScript 6 classes JavaScript sont introduites, cette méthode fournit un moyen plus facile de modéliser les concepts de POO en Javascript.

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

Ci-dessous est un squelette de la classe,l'héritage écrit dans le Nœud.js ( Utilisé Nœud.Version 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();
37
répondu Piyush Sagar 2016-01-18 03:57:36

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

Il y a un exemple de comment l'utiliser sur la page liée.

14
répondu badsyntax 2013-08-12 13:30:04

C'est la meilleure vidéo sur le JavaScript orienté objet sur internet:

Le Guide définitif de JavaScript orienté objet

Regardez du début à la fin!!

Fondamentalement, Javascript est un langagebasé sur un Prototype qui est assez différent des classes en Java, C++, C# et d'autres amis populaires. La vidéo explique les concepts de base beaucoup mieux que toute réponse ici.

Avec ES6 (sorti en 2015), nous avons obtenu un mot-clé "class" qui permet nous utilisons des "classes" 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: entrez la description de l'image ici

7
répondu etayluz 2017-03-01 04:20:02

Dans la communauté Javascript, beaucoup de gens soutiennent que la POO ne devrait pas être utilisée car le modèle prototype ne permet pas de faire une POO stricte et robuste en mode natif. Cependant, je ne pense pas que la POO soit une question de langage mais plutôt une question d'architecture.

Si vous voulez utiliser une vraie POO forte dans Javascript / Node, vous pouvez jeter un oeil 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épendance, ...). Il vous permet également d'utiliser les mêmes classes sur les côtés serveur (nœud) et client (navigateur). De plus, vous pouvez coder vos propres modules danf et les partager avec n'importe qui grâce à Npm.

4
répondu Gnucki 2014-11-25 16:59:15