2

For a JavaScript project we want to introduce object inheritance to decrease code duplication. However, I cannot quite get it working the way I want and need some help.

We use the module pattern. Suppose there is a super element:

a.namespace('a.elements.Element');
a.elements.Element = (function() {
    // public API -- constructor
    Element = function(properties) {
        this.id = properties.id;
    };

    // public API -- prototype
    Element.prototype = {
        getID: function() {
            return this.id;
        }
    };

    return Element;
}());

And an element inheriting from this super element:

a.namespace('a.elements.SubElement');
a.elements.SubElement = (function() {
    // public API -- constructor
    SubElement = function(properties) {
        // inheritance happens here
        // ???
        this.color = properties.color;
        this.bogus = this.id + 1;
    };

    // public API -- prototype
    SubElement.prototype = {
        getColor: function() {
            return this.color;
        }
    };

    return SubElement;
}());

You will notice that I'm not quite sure how to implement the inheritance itself. In the constructor I have to be able to pass the parameter to the super object constructor and create a super element that is then used to create the inherited one. I need a (comfortable) possibility to access the properties of the super object within the constructor of the new object. Ideally I could operate on the super object as if it was part of the new object.

I also want to be able to create a new SubElement and call getID() on it.

What I want to accomplish seems like the traditional class based inheritance. However, I'd like to do it using prototypal inheritance since that's the JavaScript way. Is that even doable?

Thanks in advance!

EDIT: Fixed usage of private variables as suggested in the comments. EDIT2: Another change of the code: It's important that id is accessible from the constructor of SubElement.

j0ker
  • 4,069
  • 4
  • 43
  • 65
  • 1
    Just to let you know: Your "private" variable `id` will be shared by all instances, so it's rather a static variable. Whenever you create an instance of `Element`, it will override the current value of `id`. You cannot use prototype functions and "private" *instance* variables like this. – Felix Kling Jun 25 '12 at 14:40
  • Module pattern is separate from inheritance and OOP. Also variables trapped inside closures are not private fields of an object. – Esailija Jun 25 '12 at 14:44
  • @Esailija: Although they're frequently used as such, per Crockford's pattern. But the closure would have to be the call to the constructor rather than the call to the module factory. :-) – T.J. Crowder Jun 25 '12 at 14:46
  • @Esailija: :-) Oh, it's not all that bad. Thankfully, though, we'll be getting [true private properties](http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects) in the fullness of time. – T.J. Crowder Jun 25 '12 at 14:52
  • You're right, of course. I fixed that. – j0ker Jun 25 '12 at 15:06

2 Answers2

1

You can do class-like inheritance using JavaScript's prototypical inheritance if you like. See this other answer for a full example and discussion, which you can easily fit into your pattern.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Shouldn't this question be closed as a duplicate then? – Felix Kling Jun 25 '12 at 14:42
  • @FelixKling: I couldn't decide whether it was really a duplicate or not. Different question, basically the same answer. :-) What we need is a canonical "how do you do basic inheritance in JavaScript?" question. Perhaps the one referenced above is close enough... – T.J. Crowder Jun 25 '12 at 14:45
  • Yes, we definitely need one. I have the feeling I write about inheritance every second day. Your answer seems to cover everything. – Felix Kling Jun 25 '12 at 14:46
  • +1 to even you out, though could probably be closed as duplicate. – Shaded Jun 25 '12 at 14:48
  • Was exactly what I needed. I guess, I didn't find the answer since I didn't really know what I was looking for. Thanks! – j0ker Jun 25 '12 at 15:31
1

Try this code (the inherit method is taken from here):

function inherit(proto) {
  function F() {};     
  F.prototype = proto;
  return new F();
}

a.namespace('a.elements.SubElement');
a.elements.SubElement = (function() {
    // private properties
    var color;

    // public API -- constructor
    SubElement = function(properties) {
        color = properties.color;
    };

    //inherit from parent
    SubElement.prototype = inherit(a.elements.Element);

    //add new methods to the prototype

    SubElement.prototype.getColor = function() {
            return color;
    }

    SubElement.prototype.doSomethinkWithID = function() {
            var id = this.getID();
    }

    return SubElement;
}());
mihai
  • 37,072
  • 9
  • 60
  • 86
  • Thanks for the suggestion. However, the problem is, that I cannot access the properties of the super element within the constructor of `SubElement` which I need to. I have fixed my code to state that more clearly. Sorry about that. – j0ker Jun 25 '12 at 15:14