1

I'm creating an application which will need to have inheritance, but I don't know which way of inheritance definition to choose. I found two ways do define class inheritance, but I don't know the difference between them.

var ns = {}; // Namespace
ns.DocBase = function (id, name) {
    this._id = id;
    this._name = name;
};
ns.DocBase.prototype.constructor = ns.DocBase;
ns.DocBase.prototype._id = null;
ns.DocBase.prototype._name = null;

Document inherits from DocBase by setting his prototype to Object.create(ns.DocBase.prototype):

ns.Document = function (id, name, content) {
    ns.DocBase.call(this, id, name);
    this._content = content;
};

ns.Document.prototype = Object.create(ns.DocBase.prototype);
ns.Document.prototype.constructor = ns.Document;
ns.Document.prototype._content = null;

Folder inherits from DocBase by setting his prototype to new ns.DocBase()

ns.Folder = function (id, name, childs) {
    ns.DocBase.call(this, id, name);

    if (Array.isArray(childs)) {
        childs.forEach(function (elem) {
            if (elem instanceof ns.Folder) {
                this._folders.push(elem);
            } else if (elem instanceof ns.Document) {
                this._documents.push(elem);
            }
        });
    }
}
ns.Folder.prototype = new ns.DocBase();
ns.Folder.prototype.constructor = ns.Folder;
ns.Folder.prototype._documents = [];
ns.Folder.prototype._folders = [];

Both ways of inheriting works and in both ways I have access to properties from inherited class, but I want to know which way of defining inheritance in javascipt classes is better and why.

Epsil0neR
  • 1,676
  • 16
  • 24
  • Prototype is a shared object what could happen when you set an instance (with instance members) of parent as the prototype of child is shown here. http://stackoverflow.com/a/16063711/1641941 – HMR Mar 04 '14 at 00:12

1 Answers1

1

Particularly in the case you presented, they are pretty the same, a tiny advantage of object.create(ns.DocBase.prototype) is that it does inherit only DocBase.prototype without executing the constructor, so there are less space allocated than using new (_id and _content not allocated on the prototype of the objects).
Here's a graph to illustrate the difference (some parts are omitted):

enter image description here

notice the extra _id and _name in folder._prototype.

the real bad practice in your example is that you re declared properties in prototype object:

ns.DocBase.prototype._id = null;
ns.DocBase.prototype._name = null;

an unnecessary step since you are are calling DocBase.call(this) in the document (and folder) constructor.

Amine Hajyoussef
  • 4,381
  • 3
  • 22
  • 26
  • I'm declaring properties in prototype (`ns.DocBase.prototype._id = null;`) because I'm want to easily find which objects which properties have without looking inside constructor, as I think that constructor must only manipulate with his properties, but not declare new properties. Also it is easier way to read code. – Epsil0neR Mar 03 '14 at 20:20
  • I think a better and equivalently readable approach is to declare object properties at the beginning of the constructor like you did in the DocBase constructor(declaring new properties), because first you avoid the extra overhead, and second it's more maintainable (easier to remove and add new properties). – Amine Hajyoussef Mar 03 '14 at 20:44
  • Declaring "default" properties on the prototype is *not* a bad practice, but indeed completely unnecessary here. – Bergi Mar 04 '14 at 13:13
  • as far as I know, the only benefit of declaring properties in the prototype is to make inheritance (using `object.create`) to work smoothly (let child access parent property without the requirement of calling the parent constructor), but that violate object orientation principles. is there any other advantage I'm not aware of? – Amine Hajyoussef Mar 04 '14 at 13:23
  • The OOP principle you're looking for is "delegation" and so trivial with prototypes that you don't even see it :-) Not setting a property in the constructor does not violate anything. – Bergi Mar 05 '14 at 13:31