1

This is probably a stupid question, but is there way in Javascript (ES5 preferred) to "extend" a class function similar to how i can i extend a parent' function in PHP ?

Basicly, i have this class hierarchy from System -> Weapon -> Dual and i would like Dual to use the code from System.setState() and then do some more stuff.

Note i use pre ES6 syntax for my hierarchy.

function System(system){
    this.setState = function(){
        //do stuff
    }
}

function Weapon(system){
    System.call(this, system);
}
Weapon.prototype = Object.create(System.prototype);


function Dual(system){
    Weapon.call(this, system);

    this.setState = function(){ // this is the problem
        System.prototype.setState(); // error - not defined
        //Weapon.protoype.setState() doesnt work either
        //do more stuff
    }
}
Dual.prototype = Object.create(Weapon.prototype);
user431806
  • 396
  • 5
  • 17
  • Possible duplicate of [How to extend Function with ES6 classes?](http://stackoverflow.com/questions/36871299/how-to-extend-function-with-es6-classes) – Bas Apr 23 '17 at 10:15
  • No, because im not using ES6, as i describe in post and code. – user431806 Apr 23 '17 at 10:16
  • Well, in your case you could remove all `this.setState` declarations from your Dual class, as it should already be inherited from the `System` class. – XCS Apr 23 '17 at 10:18
  • Im not sure if im just bad at explaining but the code should explain it pretty well. Dual.setState() does more stuff in addition to what System.setState does. Hence, i cant remove it. I want it to result in using all th code from System.setState and then some. – user431806 Apr 23 '17 at 10:21

2 Answers2

3

Because setState is an instance property of System it does not exist on System.proptotype so you can't call it using System.prototype.setState.call. If you want to call it in this case, just create an object from System like so

function Dual(system){
    Weapon.call(this, system);
    var parent = new System(system);

    this.setState = function() {
        parent.setState(); // done
    }
}

Instance properties are duplicated on each individual object ( they don't share). Whereas, prototype properties will be shared among children( they are not duplicated on child classes). To make all System 's subclasses share setState function, add it to System 's prototype

function System (arg) { ... }
System.prototype.setState = function () {...}

Now in your child classes, you can do

function Dual(system){
    Weapon.call(this, system);

    this.setState = function() {
        System.prototype.setState.call(this); // done
    }
}
Trash Can
  • 6,608
  • 5
  • 24
  • 38
1

First, you should set your instance methods on the prototype:

System.prototype.setState = function() {
    // your stuff
}

This will improve performance and allow you to inherit the method without constructing a System instance.

Then, you just need to call System's version of setState on the right object (the instance of Dual) instead of calling it on System.prototype:

Dual.prototype = Object.create(Weapon.prototype, {

    'setState': { value: function(){
        System.prototype.setState.call(this) // fixed
        // other stuff
    }}
})
Touffy
  • 6,309
  • 22
  • 28
  • How much performance will it bring ? I have several douzen "System"s instantiated, they have 700 lines of code each, of which 670 are methods. How "valueable" would it be to reorder them "out" of the class into the prototype ? – user431806 Apr 23 '17 at 11:25
  • Each method that's added onto the instance directly by the constructor is copied for each instance, so you multiply the memory footprint by the number of instances, and instantiation is a bit longer (quite a bit, I imagine, for 670 lines of functions, but I can't measure without your code). Instead, when added to the prototype, there is a single copy of each method and all instances use it (there is a minuscule cost for looking up the prototype chain, about 1% according to [jsperf](https://jsperf.com/prototype-vs-factory-performance/20)). – Touffy Apr 23 '17 at 14:55