Daniela Daniela - 2 months ago 8
Javascript Question

Javascript constructor functions in "subclass", correct notation?

I am trying to come to grips with javascript inheritance. My example code starts like this:

var example = example || {};
example.Classes = {};

(function() {
var example = example || {};
example.Classes = {};

var privateVar = 25;
function Superclass() {
this.x = privateVar;
}
Superclass.prototype = {
move: function(x){
this.x += x;
console.log("Superclass move",this.x);
},
dance: function(x){
this.x += x*2;
}
};

function Subclass() {
Superclass.apply(this, arguments);
this.y = 0;
};
Subclass.prototype = Object.create(Superclass.prototype);
Subclass.prototype.constructor = Subclass;


This is the successful continuation:

Subclass.prototype.dance = function(x, y) {
this.x -= (x + privateVar);
this.y -= y;
console.log("Subclass dance", this.x, this.y)
};
example.Classes.Superclass = Superclass;
example.Classes.Subclass = Subclass;
window.example.Classes = example.Classes;
}());

var success = new example.Classes.Subclass();
success.dance(5,4);
success.move(6);


console output: Subclass dance -5 -4

console output: Superclass move 1



And now the continuation that fails - what is wrong here? Why can't I use this way of writing the subclass constructor functions?

Subclass.prototype = {
dance: function(x, y) {
this.x -= (x + privateVar);
this.y -= y;
console.log("Subclass dance", this.x, this.y)
}
};

example.Classes.Superclass = Superclass;
example.Classes.Subclass = Subclass;
window.example.Classes = example.Classes;
}());

var failure = new example.Classes.Subclass();
failure.dance(5,4);
failure.move(6);


console output: Subclass dance -5 -4

console output: ERROR: failure.move is not a function

Answer

Why can't I use this way of writing the subclass constructor functions?

Because you're blowing away the object that used to be on the Subclass.prototype property (the one from Object.create(Superclass.prototype)) and replacing it with an object whose prototype is Object.prototype with just one property, dance.

Once you've created the Subclass.prototype object, you always want to augment it as you did originally:

Subclass.prototype.dance = /*...*/;

not replace it:

// Not this
Subclass.prototype = { dance: /*...*/ };

ES2015 added a handy function for merging properties from one object (or a series of them) into a target object: Object.assign. It can be polyfilled (mostly) for older JavaScript engines. Using that, you could do:

Object.assign(Subclass.prototype, {
    dance: function dance() { /* ... */ },
    skip:  function skip()  { /* ... */ },
    jump:  function jump()  { /* ... */ }
});

Having said that, here in 2016, I would suggest using the class feature added in ES2015 (transpiling if necessary for older JavaScript engines):

class Superclass {
    constructor() {
        //...
    }

    method() {
        // ...
}

class Subclass extends Superclass {
    constructor() {
        super();
        // ...
    }

    anotherMethod() {
        // ...
    }
}