Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Coming from a Java kind of OOP, I miss a lot of things in JavaScript. I am working on a Node.Js project, and I would like to use an OO approach.

Looking around and asking in StackOverflow I came up with this example scenario (jsFiddle).

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.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.prototype.constructor.apply( this, arguments );
    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)

Is this approach correct (best practices)? Should I do something differently?

The idea would be then to create a js file for each class and use module.exports.. in Node.Js I will also use Mongoose to store the objects into a database, I guess I will need a way to translate my objects into Mongoose Models and back..

EDIT: how would one implement private methods used internally?

share|improve this question
    
Like I showed in my answer, you can prefix a method or field with an underscore to communicate that this is an internal method or field, and it should not be accessed directly. –  Esailija Aug 12 '13 at 17:02
    
oh! right! thanks :) –  fusio Aug 12 '13 at 17:49
    
As per the SO question : There is nothing really specific about OO JS in node.js. There is just OO JS. Your question is about translating Java OOP techniques to JS, which is just not right. I think it better you spent the same time/energy in learning how JS's prototype-based model works, and how you can use it to your advantage. –  konijn Aug 12 '13 at 19:14
    
@tomdemuyt But I am not. I just stated that I am coming from a Java background -- it is not my intention to use Java style OO in JS. However, I can only work with what I know: hence the question, how to do OO in JS? –  fusio Aug 12 '13 at 19:19
    
@fusio btw can you specify what you miss from Java object model? –  Esailija Aug 12 '13 at 23:33

1 Answer 1

Pretty good code.

From an OOP perspective, this is exactly right. From a formatting perspective, this is almost flawless. I hardly have anything to say about this code, but I see very little that I would change.

The only issue that I see is an irregular formatting choice. These commas:

Shape.prototype = {
    constructor: Shape
    , getId: function() {
        return this.id
    }
    , getSize: function() {
        return this.size
    }
    , setSize: function (size)  {
        this.size = size
    }
}

should be like this:

Shape.prototype = {
    constructor: Shape,
    getId: function () {
         return this.id
    },
    getSize: function () {
         return this.size
    },
    setSize: function (size)  {
        this.size = size
    }
};

Oh and you need to read this world-changing answer about OO practices in JS.

Be sure to press B while reading that, because if not, you'll evolve into a legendary OOP developer.

enter image description here

share|improve this answer
    
comma first style.. I am still undecided if I like it or not, working with the classic style atm ;) –  fusio Jul 28 at 14:50
    
@fusio That is of course, perfectly ok. It's good to know the conventional practice though in case you decide to work on a group project. –  jt0dd Jul 28 at 15:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.