Search code examples
javascriptobjectinheritanceprototypal-inheritance

Inheritance in JavaScript: How can I call the object parent?


I'm building a multi-source audio player in JavaScript and my goal is to code several providers classes (for Youtube, Soundcloud, etc.) that would extend a base class, so each provider would have the same methods and properties, but I would be able to customize them for each provider.

Here's a simplified example.

The base class looks like this :

function Player_Provider(slug) {
    this.slug = slug;
    console.log("Player_Provider init: " + this.slug);
};

Player_Provider.prototype.loadUrl = function(url) {
    console.log("provider "+this.slug+" - load URL: " + url);
};

I "extend" this class for providers; for example:

function Player_Provider_Youtube() {
  Player_Provider.call(this, 'youtube');
}

Player_Provider_Youtube.prototype = Object.create(Player_Provider.prototype); //inherit methods
Player_Provider_Youtube.prototype.constructor = Player_Provider_Youtube; //fix constructor

Player_Provider_Youtube.prototype.loadUrl = function(url) {
    Player_Provider.prototype.loadUrl(url);
}

And then I register it like this:

var providers = [];
providers.youtube = new Player_Provider_Youtube();
providers.youtube.loadUrl("https://www.youtube.com/watch?v=5SIQPfeUTtg");

Which outputs in the console:

Player_Provider init: youtube
provider undefined - load URL: https://www.youtube.com/watch?v=5SIQPfeUTtg

As you can see, the console outputs:

"provider undefined - load URL..."

when I would like it to output:

"provider youtube - load URL..."

The idea here is that in each function of the provider (which would every time override a function from the base class), I would call the "parent" function first, at least to output a console message like here; and eventually to run some code - in the idea of having the most clean code possible.

I'm more comfortable with PHP and it's the first time I'm trying to do that kind of stuff using JavaScript.

How would you do this and why is my variable undefined?


Solution

  • In ES5 and earlier, it's a pain. You use call or apply, and as you've found, it's really verbose.

    Player_Provider_Youtube.prototype.loadUrl = function(url) {
        Player_Provider.prototype.loadUrl.call(this, url);
        // ------------------------------^^^^^^^^^^^
    }
    

    I found that painful enough I wrote a library to deal with it (here), but it's obsolete now.

    But, here in 2017, you don't do that anymore; instead, you use ES2015's class syntax and transpile (with something like Babel) so it runs on older JavaScript engines:

    class Parent {
        method() {
            console.log("Parent method");
        }
    }
    class Child extends Parent {
        method() {
            console.log("Child method");
            super.method();
        }
    }
    new Child().method();

    That handles all the nasty plumbing for you. It's still the same prototypical inheritance + constructor functions that it was before ES2015, it's just much simpler syntax for it. (And enables a couple of things we couldn't do with the old syntax.)