2

I am building a function that allows an object to be extended by any other object

Object.prototype.extend = function(constructor, args) {
    var proto = this;
    while(proto.__proto__.constructor !== Object) {
        proto = proto.__proto__
    }
    proto.__proto__ = new constructor(args)
    console.log(this); 
}

the method would be called like this:

function ChildModelConstructor(1,2,3) {
    this.extend(ParentModel, arguments)
}
or
instanceOfChildModel.extend(ParentModel, [1,2,3])

the problem is if I call new like this:

new constructor(args)

the constructor of the parent object receives argument which is an arguments object or array.

What I would like is to be able to call

new constructor.apply(args)

or something similar, I am not trying to change the context of this new, apply is the only method of calling a method using an args object or an array that I am aware of.

Thanks for the help :)

Update, I found a better way

Here's a better approach to Inheritance I came up with, it avoids using the depreciated proto

There are several advantages to this method, over other inheritance schemes I've found. The biggest is that it does not merge multiple levels of the proto chain. Many schemes mix the childClass's proto methods with the parent classes instance variables, or worse, all methods and properties from the parents initialization directly into the main body of the childClass.

The drawbacks are, it is single inheritance, and you cannot change the inheritance of a single instance, since the prototype property belongs to the Constructor.

Function.prototype.inherit = function(parentClass) {
    var newPrototype = Object.create(Object.create(parentClass.prototype));
    for(key in this.prototype){
        newPrototype[key] = this.prototype[key];
    }
    this.prototype = newPrototype;    
    this.prototype.constructor = this;
    this.prototype.parentClass = parentClass;
    this.prototype.initParent = function(args) {
        var proto = Object.getPrototypeOf(Object.getPrototypeOf(this))
        this.parentClass.apply(proto, args);
    }
    this.prototype.uber = function() {
        return Object.getPrototypeOf(Object.getPrototypeOf(this));
    }        
}

and you can set up the inheritance like this:

function Model(n) {
    this.initParent(arguments)
    this.test = n*2;
}
Model.inherit(BaseClass);

Here is a slightly more detailed version in JSFiddle http://jsfiddle.net/michaelghayes/2rHgK/​​

MiGnH
  • 428
  • 4
  • 11
  • 2
    possible duplicate of [Use of .apply() with 'new' operator. Is this possible?](http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible) – Felix Kling May 20 '12 at 23:21
  • I think you are right, I have moved onto doing inheritance a different way, I'll edit/close the question – MiGnH May 21 '12 at 02:13

2 Answers2

0

This is untested, but I think it will work. Replace:

proto.__proto__ = new constructor(args)

With:

proto.__proto__ = {};
proto.__proto__.prototype = constructor.prototype;
constructor.apply(proto.__proto__, args);

Take note that __proto__ is deprecated.

Paul
  • 139,544
  • 27
  • 275
  • 264
  • 1
    This will add the keys that are generated by the constructor to the last object in the proto chain before Object, but it will not add the proto chain from the constructor. For example if you have a method ParentClass.prototype.doSomethin = function() {return 4}; that will not be available in the child object – MiGnH May 20 '12 at 23:27
0

its better not to attach things to the object prototype and just set up the inheritance manually:

Model function() {
  //init parent first because of chromes hidden classes
  ParentClass.apply(this, [].slice.call(arguments))
  //new instance properties
  this.something = 'something'
}

Model.prototype = Object.create(ParentClass.prototype, {
  constructor: {value: Model}
})

//Prototype props
Model.prototype.whatever = function(){return 'whatever'}

this also allows you to modify args before initing the parent since your new class shouldn't be restricted to using the exact same args as its parent

MiGnH
  • 428
  • 4
  • 11