title: JavaScript OOP in NodeJS: how?
body: <p>I am used to the classical OOP as in Java.</p>
  
  <p>What are the best practices to do OOP in JavaScript using NodeJS? </p>
  
  <p>Each Class is a file with <code>module.export</code>?</p>
  
  <p>How to create Classes?</p>
  
  <pre><code>this.Class = function() {
      //constructor?
      var privateField = ""
      this.publicField = ""
      var privateMethod = function() {}
      this.publicMethod = function() {} 
  }
  </code></pre>
  
  <p>vs. (I am not even sure it is correct)</p>
  
  <pre><code>this.Class = {
      privateField: ""
      , privateMethod: function() {}
  
      , return {
          publicField: ""
          publicMethod: function() {}
      }
  }
  </code></pre>
  
  <p>vs.</p>
  
  <pre><code>this.Class = function() {}
  
  this.Class.prototype.method = function(){}
  
  ...
  </code></pre>
  
  <p>How would inheritance work?</p>
  
  <p>Are there specific modules for implementing OOP in NodeJS? </p>
  
  <p>I am finding a thousand different ways to create things that resemble OOP.. but I have no clue what is the most used/practical/clean way.</p>
  
  <p><strong>Bonus question</strong>: what is the suggested "OOP style" to use with MongooseJS? (can a MongooseJS document be seen as a Class and a model used as an instance?)</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>here is an example in <a href="http://jsfiddle.net/eS7LE/4/">JsFiddle</a> please provide feedback.</p>
  
  <pre><code>//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)
  </code></pre>