Making subclass with .prototype and __proto__

javascript

Solution

As already said, don't use `__proto__`. It's a non-standard property. (It's standardized for JavaScript in browsers now. Still don't use it.) But

Subclass.prototype = new Superclass(); // Don't do this

is not a very good method either. What if `Superclass` expects parameters?

You have better options.

ES2015 and above

`class` handles all of this plumbing for you; complete example:

class Superclass {
    constructor(superProperty) {
        this.superProperty = superProperty;
    }
    method() {
        console.log("Superclass's method says: " + this.superProperty);
    }
}
class Subclass extends Superclass {
    constructor(superProperty, subProperty) {
        super(superProperty);
        this.subProperty = subProperty;
    }
    method() {
        super.method(); // Optional, do it if you want super's logic done
        console.log("Subclass's method says: " + this.subProperty);
    }
}

let o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

ES5 and earlier

Let `Subclass.prototype` inherit from `Superclass.prototype` only. This can be done for example with ES5's `Object.create`:

Subclass.prototype = Object.create(Superclass.prototype);
Subclass.prototype.constructor = Subclass;

And then in `Subclass`, you call `Superclass` with `this` referring to the object so it has a chance to initialize:

function Subclass() {
    Superclass.call(this); // Pass along any args needed
}

Full example:

function Superclass(superProperty) {
    this.superProperty = superProperty;
}
Superclass.prototype.method = function() {
    console.log("Superclass's method says: " + this.superProperty);
};
function Subclass(superProperty, subProperty) {
    Superclass.call(this, superProperty);
    this.subProperty = subProperty;
}
Subclass.prototype = Object.create(Superclass.prototype);
Subclass.prototype.constructor = Subclass;

Subclass.prototype.method = function() {
    Superclass.prototype.method.call(this); // Optional, do it if you want super's logic done
    console.log("Subclass's method says: " + this.subProperty);
};

var o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

ES3 and earlier

ES3 and earlier don't have `Object.create`, but you can easily write a function that sets up the prototype for you in much the same way:

function objectCreate(proto) {
    var ctor = function() { };
    ctor.prototype = proto;
    return new ctor;
}

(Note: You could half-shim `Object.create` by creating one that takes only one argument, but the multiple-argument version of `Object.create` cannot be shimmed, so it would be giving other code on the page the wrong idea if it also uses `Object.create`.)

Then you do the same thing as our ES5 example:

Full example:

function objectCreate(proto) {
    var ctor = function() { };
    ctor.prototype = proto;
    return new ctor;
}

function Superclass(superProperty) {
    this.superProperty = superProperty;
}
Superclass.prototype.method = function() {
    console.log("Superclass's method says: " + this.superProperty);
};
function Subclass(superProperty, subProperty) {
    Superclass.call(this, superProperty);
    this.subProperty = subProperty;
}
Subclass.prototype = objectCreate(Superclass.prototype);
Subclass.prototype.constructor = Subclass;

Subclass.prototype.method = function() {
    Superclass.prototype.method.call(this); // Optional, do it if you want super's logic done
    console.log("Subclass's method says: " + this.subProperty);
};

var o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

Problem

I've recently been learning javascript by writing some gnome shell extensions, and hence my understanding of Javascript has been shaped by the examples I've observed in the gnome-shell javascript sources. I have a feeling I've been understanding classes wrong and just want some clarification. I've written a few of my own subclasses, and in each case I've defined them simply by following similar code in the gnome-shell javascript source: ``` Subclass = function() { this._init.apply(this,arguments); } Subclass.prototype = { __proto__: Superclass.prototype, _init: function() { Superclass.prototype._init.call(this); }, // add other methods of Subclass here. } ``` Up to now I thought this was the standard way of making a class `Subclass` that was basically `Superclass` plus extras. I assumed that every object had a `_init` method. I've recently tried to apply the same method to make a subclass of a `Clutter.Actor` (what's important is that it's not a GNOME-shell-defined class), and realised that the above way of subclassing objects is not the standard. For one, not every class has a `_init` function as I assumed; this is just something that GNOME-shell has done in their javascript classes. So, my questions are: - Is there any documentation regarding the above method of creating subclasses? All the tutorials I've seen say to set `Subclass.prototype = new Superclass()` instead of doing the `Subclass.prototype = { __proto__:Superclass.prototype, define_prototype_methods_here }` method, but my thought is that there must be some method to it if gnome-shell uses it consistently? - If I wanted to stay as close as possible to the above way of defining classes (just so I can retain some code similarity to GNOME-shell for which I am writing extensions), what do I replace `Superclass.prototype._init.call(this)` with in `Subclass._init` to make sure that the `Subclass.prototype` gets all the methods/properties of `Superclass` (which I then add on to in my definition of `Subclass.prototype`), if the `Superclass` doesn't have an `_init` function (i.e. does it have some equivalent constructor function I call)? I'm really confused about this all so please forgive me if my question doesn't make much sense; it'll be because of the extent of my misunderstanding & confusion! EDIT: clarification: - I know the `__proto__` is not recommended because it is non-standard, but my code is never going to run in a browser - it's only ever going to run with GNOME javascript (which is basically the Mozilla javascript engine), so I don't need to worry about cross-compatibility.

Original source