WhyNotHugo
WhyNotHugo

Reputation: 9926

Extends an object with a second prototype

I've a prototype Node, of which I create several objects.

During the lifetime of these objects, I may need them to become ValueNode or PropertyNode. I currently handle this by using a helper for each "subclass", and sharing a commong interface on both helpers. Think of something like a state pattern.

However, I'd like to improve this design, by actually extending the existing objects with the aditional functionality, and not using helpers.

ie:

n = new Node();

...

// n needs to become a ValueNode
// ???

n.methodDefinedForValueNodesOnly();

Is this possible in javascript? And is it "good practice"?

Upvotes: 0

Views: 74

Answers (2)

WhyNotHugo
WhyNotHugo

Reputation: 9926

After reading this article on mixins, I ended up using the following solution (which basically uses mixins nicely).

Node = function() {};
Node.prototype.one = function() {alert(1)};

asValueNode = (function() {
  function two() {
    alert(2)
  };
  return function() {
    this.two = two;
    return this;
  }
})();

u = new Node();
// u is a usable Node.
// ...

// Make u a ValueNode
asValueNode.call(u);

u.one();
u.two();

Upvotes: 1

davidbuzatto
davidbuzatto

Reputation: 9424

In JavaScript you can perform prototype inheritance just once. You can use some framework that provide a rich class subsystem like ExtJS, Ember.js, etc. Another approach could be to iterate over the properties of the desired object and apply then to the target object. Something like this:

function Node( desc ) {
    this.desc = desc;
    this.doNodeThing = function() {
        console.log( "noding for " + this.desc );
    }
}

function FooNode( desc ) {
    this.desc = desc;
    this.doFooNodeThing = function() {
        console.log( "foo noding for " + this.desc );
    }
}

function BarNode( desc ) {
    this.desc = desc;
    this.doBarNodeThing = function() {
        console.log( "bar noding for " + this.desc );
    }
}

function inherit( obj, superObj ) {

    for ( var x in superObj ) {
        if ( typeof superObj[x] == "function" ) {
            obj[x] = superObj[x];
        }
    }
}

var n1 = new Node( "tree node" );
n1.doNodeThing();

var n2 = new Node( "folder node" );
n2.doNodeThing();

inherit( n1, new BarNode() );
n1.doBarNodeThing();
//n2.doBarNodeThing();    <= TypeError: n2.doBarNodeThing is not a function

inherit( n1, new FooNode() );
n1.doBarNodeThing();
n1.doFooNodeThing();
//n2.doFooNodeThing();    <= TypeError: n2.doFooNodeThing is not a function

The code above will add functions to the object itself, not to its prototype.

jsFiddle: http://jsfiddle.net/davidbuzatto/3cCGC/

Upvotes: 0

Related Questions