7

I want to know why the three.js code is structured like this:

THREE.Camera = function(){
    THREE.Object3D.call(this);
    //add more Camera specific properties and methods
}

THREE.Camera.prototype = new THREE.Object3D();
THREE.Camera.prototype.constructor = THREE.Camera;

THREE.Camera.prototype.//add more camera specific methods...

I want to know why they call the base constructor in the current constructor and also for the prototype?

In MDN they show a pattern like this:

subType = function(){
    //new properties for subType
}

subType.prototype = new baseType();

They don't have the call to the base constructor in the subType constructor, so why does THREE.js do this?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Daniel Robinson
  • 13,806
  • 18
  • 64
  • 112

1 Answers1

8

Since each THREE.Object3D instance inherits from THREE.Object3D.prototype, by setting THREE.Camera.prototype this way, each THREE.Camera instance will also inherit from THREE.Object3D.prototype.

If you don't do this, THREE.Camera instances won't inherit any properties assigned to THREE.Object3D.prototype.

So, both parts are important:

  • By setting THREE.Camera.prototype appropriately, new instances will inherit from THREE.Object3D.prototype and these properties are shared by all instances.

  • By calling the "parent" constructor function you are initializing each instance with instance-specific data.


That said, setting the prototype like this is not the best approach. What if THREE.Object3D expects arguments without which the constructor would not work?

A better approach is to create an empty object which inherits from THREE.Object3D.prototype, since this is all you need:

THREE.Camera.prototype = Object.create(THREE.Object3D.prototype);
THREE.Camera.prototype.constructor = THREE.Camera;

Reference: Object.create

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I agree to use Object.create instead! – Van Coding Jun 19 '12 at 13:02
  • If you want the methods from Object3D prototype to be available to Camera objects could you not just assign Camera.prototype directly to Object3D.prototype -> `THREE.Camera.prototype = THREE.Object3D.prototype` ? why the need to create a new copy of it? so you can add new methods to it without effecting the original copy? – Daniel Robinson Jun 19 '12 at 13:07
  • @DannyR: Exactly. If you'd do `THREE.Camera.prototype = THREE.Object3D.prototype` then any changes you make to `THREE.Camera.prototype` would also affect `THREE.Object3D.prototype`. That's why you want this one level of indirection (as I would call it). Regarding your edit, this is the second point in my list. You don't have to call the parent constructor if you don't want to, but it is reasonable to do so. – Felix Kling Jun 19 '12 at 13:18
  • https://github.com/mrdoob/three.js/issues/2080 is the issue which checks tries to exploit the this feature in ecmascript – Gero3 Jun 26 '12 at 10:50
  • 2
    FYI: https://github.com/mrdoob/three.js/commit/cdfc4f3b8adc635e1a635ab12250c71141f95e9d ^^ – mrdoob Jun 26 '12 at 19:57
  • 1
    @mrdoob: :) I'm kind of proud to have somehow contributed to the three.js library! I'm not using it, since this is not my field, but it looks like a really really good library. Wish you all the best with it! – Felix Kling Jun 26 '12 at 22:08