33

Assume I have a class like this:

function Widget() {
    this.id = new Date().getTime();
    // other fields
}
Widget.prototype = {
    load: function(args) {
        // do something
    }
}

From this class I created some other classes which inherit the same prototype but have some added methods. What I want to do is being able to define a load() method in the sub-classes which first calls the parent method and then execute some code. Something like:

SpecialWidget.prototype = {
    load: function(args) {
        super.load(args);
        // specific code here
    }
}

I know there's no super keyword in Javascript but there must be a way to do this.

Cœur
  • 34,719
  • 24
  • 185
  • 251
The Coding Monk
  • 7,294
  • 12
  • 39
  • 53

5 Answers5

42

You can simulate it like this:

SpecialWidget.prototype = {
    load: function(args) {
        Widget.prototype.load.call(this, args);
        // specific code here
    }
}

Or you can create your own super property like this:

SpecialWidget.prototype.parent = Widget.prototype;

SpecialWidget.prototype = {
    load: function(args) {
        this.parent.load.call(this,args);
        // specific code here
    }
}
karim79
  • 334,458
  • 66
  • 409
  • 405
3

so first, you set up your 'subclass' like so

function SubClass(name) {
    Super.call(this);

    // stuff here
}

SubClass.prototype = new SuperClass(null);
SubClass.prototype.constructor = SubClass;

and then you can do

SuperClass.prototype.theMethod.apply(this);

from within a subclass implementation to specifically invoke the super's implementation.

hvgotcodes
  • 114,474
  • 29
  • 200
  • 234
  • For those, like me, that questioned the difference between this approach and the call in the answer, the short answer is there is none. The long answer is provided by mozilla here... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply – Jackie Aug 20 '15 at 13:43
1

I don't know if this is the best solution, but you could do something like this:

function Widget() {
    this.id = new Date().getTime();
}
Widget.prototype.load = function(args) {
   alert( 'parent load' );
};

SpecialWidget = function(){};

   // Make the prototype of SpecialWidget an instance of Widget
var proto = SpecialWidget.prototype = new Widget;

   // Give the prototype a function that references the "load" from Widget
proto.parent_load = proto.load;

   // Give SpecialWidget its own "load" that first calls the parent_load
proto.load = function( args ) {
    this.parent_load( args );
    alert( 'special load' );
};

var inst = new SpecialWidget;

inst.load();

This makes the prototype of SpecialWidget an instance of Widget so that it inherits all that Widget has.

Then it makes a reference to the load() of Widget called parent_load(), and creates its own load() that calls the parent_load() when invoked.

user113716
  • 310,407
  • 61
  • 442
  • 435
0

Using Simple Javascript Class:

Class.extend('Widget', {
  load: function () {
    alert('foo');
  }
});

Widget.extend('SpecialWidget', {
  load: function () {
    this.super();
    alert('bar');
  }
});

new Widget().load(); // Alert: 'foo'
new SpecialWidget().load(); // Alert: 'foo' and 'bar'

Take a look at Simple Javascript Class Project, Simple JavaScript Inheritance and Inheritance Patterns in JavaScript.

Eduardo Cuomo
  • 16,091
  • 5
  • 104
  • 88
0

It would be possible to store the old value of the load method in a closure, if you did your overriding like this:

function Widget() {
    this.id = new Date().getTime();
    // other fields
}

Widget.prototype = {
    load: function(args) {
        // do something
        alert("Widget Prototype Load");
    }
};

function SpecialWidget(){
};

SpecialWidget.prototype = new Widget();

(function(){
    var oldLoad = SpecialWidget.prototype.load;
    SpecialWidget.prototype.load = function(){
        oldLoad();
        alert("new Load");
    };
}());


var x = new SpecialWidget();
x.load();

It works, but I'm not sure if it's the best method.

david
  • 17,135
  • 4
  • 41
  • 57