Artefacto
Artefacto

Reputation: 97835

Run additional action after constructor

Is it possible to change a constructor so that some extra action is run after an object is created. I tried something like:

var origFoo = Foo
Foo = function() {
    origFoo.apply(this, arguments);
    /* extra actions */
}
Foo.prototype = new origFoo();

but this has several problems like the constructor being run twice or changing the prototype chain.

Upvotes: 1

Views: 363

Answers (1)

Tibos
Tibos

Reputation: 27833

You are very close. You should assign the Foo.prototype to the origFoo.prototype in order to get the same prototype chain. Everything else is spot on!

Example:

var Foo = function () {
    console.log('OriginalFoo');
};

Foo.prototype.method1 = function () {
    console.log('Method1');
};

OriginalFoo = Foo;

Foo = function () {
    OriginalFoo.apply(this, arguments);
    console.log('NewFoo');
};

Foo.prototype = OriginalFoo.prototype;

Foo.prototype.method2 = function () {
    console.log('Method2');
};

var x = new Foo();

x.method1();
x.method2();

Demo: http://jsbin.com/ibatah/1/edit?js,console,output

PS: There still is the problem of static-like properties (Foo.prop), but i'm afraid i don't have a solution for that other than copying them one at a time.

EDIT: Solution for special constructors.

Indeed there are constructors which don't like to be called as functions ex: Image. To get over it, you can do the more awkard solution below. You take advantage of the fact that you can return an object from the constructor and it takes the place of the one created with new. In the overridden constructor you must always use this new object when calling methods instead of this.

var Foo = function(a,b,c) {
  console.log('OriginalFoo',a,b,c);
};
Foo.prototype.prop1 = 'Property1';
Foo.prototype.method1 = function() {
  console.log('Method1', this.prop1);
};


OriginalFoo = Foo;
Foo = function(a,b,c) {
  var obj = new OriginalFoo(a,b,c);

  obj.init('Changed...'); // or this.init.call(obj,'Changed!'); 
  this.init('Not Changed'); // applies to a discarded object, has no effect

  console.log('NewFoo');
  return obj;
};

Foo.prototype = OriginalFoo.prototype;

Foo.prototype.prop2 = 'Property2';

Foo.prototype.method2 = function() {
  console.log('Method2', this.prop2);
};
Foo.prototype.init = function(param) {
  this.prop2 = param;
};



var x = new Foo('1','2','3');
console.log(x.prop1);
console.log(x.prop2);
x.method1();
x.method2();

Demo: http://jsbin.com/ibatah/2/edit?js,console,output

Upvotes: 3

Related Questions