1

I wonder if it's possible to instantiate subclasses in javascript by automatically using the super class's constructor.
Consider this (inspired by this other question here on SO):

function A(prop) {
    this.prop = prop;
}
A.prototype.whatAmI = function() {
    console.log(
        "I'm an instance of %s, my prop is %s",
        this instanceof A1? "A1" : "A2",
        this.prop
    );
};

function A1() {
    A.apply(this, arguments);
}
A1.prototype = new A();
A1.prototype.constructor = A1;

function A2() {
    A.apply(this, arguments);
}
A2.prototype = new A();
A2.prototype.constructor = A2;

var a1 = new A1("foo").whatAmI(); //I'm an instance of A1, my prop is foo
var a2 = new A2("bar").whatAmI(); //I'm an instance of A2, my prop is bar

However, referring to this article, in the first example I came across this line of code:

Cat.prototype.constructor = Cat;
//Otherwise instances of Cat would have a constructor of Mammal

I thought that's exactly what I needed: that instances of A1 and A2 have the constructor of A. Unfortunately commenting out A1.prototype.constructor = A1 and emptying A1's body (same goes for A2) does not work:

function A1() {}
A1.prototype = new A();

function A2() {}
A2.prototype = new A();

var a1 = new A1("foo").whatAmI(); //I'm an instance of A1, my prop is undefined
var a2 = new A2("bar").whatAmI(); //I'm an instance of A2, my prop is undefined

Finally, changing A's constructor to use the arguments object instead of explicitly passing prop has no effect either:

function A() {
    this.prop = arguments[0];
}

Is it even possible, with a little fiddling around with the prototype property, to achieve what I want?

Community
  • 1
  • 1
Andrea Aloi
  • 971
  • 1
  • 17
  • 37

1 Answers1

4
Cat.prototype.constructor = Cat;
//Otherwise instances of Cat would have a constructor of Mammal

I thought that's exactly what I needed: that instances of A1 and A2 have the constructor of A.

No, that's not what they meant. The A1 and A2 functions are still their own constructors that are getting invoked, and you cannot change that.

The problem that the article describes is that the .constructor property that all instances inherit to point out their constructor is no longer valid when you overwrite AX.prototype. See also What is the `constructor` property really used for? (and linked questions).

Unfortunately commenting out A1.prototype.constructor = A1 and emptying A1's body (same goes for A2) does not work.

By emptying the body, it doesn't do anything any more. You still will need to call A explicitly, you won't get around that. What you could do is create a generic factory that creates subclasses for A that don't do anything special, but I don't think it's worth it.

Oh, and not to forget: You should not use new for creating prototypes!

subclass(parent) {
    function Child() {
        parent.apply(this, arguments);
    }
    Child.prototype = Object.create(parent.prototype);
    Child.prototype.constructor = Child;
    return Child;
}

function A(prop) {
    this.prop = prop;
}
A.prototype.whatAmI = function() {
    console.log(
        "I'm an instance of %s, my prop is %s",
        this instanceof A1? "A1" : "A2",
        this.prop
    );
};
var A1 = subclass(A),
    A2 = subclass(A);
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375