Search code examples
javascriptoopprototypesubclassing

Javascript Subclassing. Setting the constructor property


For years I've been writing/extending my classes like so:

function Container(name, contents, logErrors){
    this.name = name;
    this.contents = contents;
    this.logErrors = logErrors || false;
}

function Group(contents){
    this.id = new Date().getTime();
    Container.call(this, 'Group_'+ this.id, contents);
}
Group.prototype = Object.create(Container.prototype);
Group.constructor = Group; 

and yet, in some places I've seen the constructor property being assigned on the prototype of the subclass rather than directly on the subclass:

function Group(contents){
    this.id = new Date().getTime();
    Container.call(this, 'Group_'+ this.id, contents);
}
Group.prototype = Object.create(Container.prototype);
Group.prototype.constructor = Group; // <-----

Which is correct?

a) Group.prototype.constructor = Group;  
b) Group.constructor = Group;  
c) both a AND b  
d) neither a nor b  

Please cite your source if possible.


Solution

  • You should always use a) Here's the reason why.

    function Container(){
        // code
    }
    function Group(){
        // code
    }
    

    Observe that at this point of time

    console.log(Group.prototype.constructor === Group);
    // true
    console.log(Group.constructor === Function);
    // true
    

    Now if you do

    Group.prototype = Object.create(Container.prototype);
    

    You loose the original Group.prototype and replaces all its methods as well. Which means you also lose the original Group.prototype.constructor as well.

    Hence you may observe that at this point of time.

    console.log(Group.prototype.constructor === Container);
    // true
    

    Now if you want something like a copy method.

    Group.prototype.copy = function() {  
        return new this.constructor(this.contents);
    };
    

    You may end up getting the result

    var group1 = new Group();
    console.log(group1.copy() instanceof Group);
    // false
    

    Which may not be expected.

    But if you would have done

    Group.prototype.constructor = Group;
    

    Then the results are as expected

    console.log(group1.copy() instanceof Group);
    // true
    

    Also you can read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance

    Hope that helps.