javascriptinheritance

Why use a roundabout way of constructing a prototype of a derived constructor, instead of simply constructing a base instance?


I am learning the basics of OOP in JavaScript and came across an inheritance example which is difference than what I've typically seen.

Typical:

ChildClass.prototype = new ParentClass();

Alternate Method:

function clone(object) {
  function OneShotConstructor(){}
  OneShotConstructor.prototype = object;
  return new OneShotConstructor();
}

SecondClass.prototype = clone(FirstClass.prototype);

Why would the latter be preferred when creating an object whose prototype is another object?


Solution

  • Because you will invoke the constructor of the custom type (a.k.a. class) you are trying to inherit from. And that might have side effects. Imagine the following:

    var instancesOfParentClass = 0;
    function ParentClass (options) {
      instancesOfParentClass++;
      this.options = options;
    }
    
    function ChildClass () {}
    ChildClass.prototype = new ParentClass();
    

    Your counter has been incremented, but you didn't really create a useful instance of ParentClass.

    Another problem, is that all instance properties (see this.options) will be present on ChildClass' prototype, and you probably don't want that.

    Note: When using constructor, you might have instance properties, and shared properties. For example:

    function Email (subject, body) {
      // instance properties
      this.subject = subject;
      this.body = body;
    }
    
    Email.prototype.send = function () {
      // do some AJAX to send email
    };
    
    // create instances of Email
    emailBob = new Email("Sup? Bob", "Bob, you are awesome!");
    emailJohn = new Email("Where's my money?", "John, you owe me one billion dollars!");
    
    // each of the objects (instances of Email) has its own subject 
    emailBob.subject // "Sup? Bob"
    emailJohn.subject // "Where's my money?"
    
    // but the method `send` is shared across instances
    emailBob.send === emailJohn.send // true