Jump to content

Object inheritance in the tutorials confuses me


Recommended Posts

var Bullet = function (game, key) {

        Phaser.Sprite.call(this, game, 0, 0, key);

        this.texture.baseTexture.scaleMode = PIXI.scaleModes.NEAREST;


        this.checkWorldBounds = true;
        this.outOfBoundsKill = true;
        this.exists = false;

        this.tracking = false;
        this.scaleSpeed = 0;


    Bullet.prototype = Object.create(Phaser.Sprite.prototype);
    Bullet.prototype.constructor = Bullet;

Specifically here, So I don't have a background in Javascript, mostly I've worked in C++

What confuses me here is it sprite object is called in bullet already so why do you need to use Object.create to inherit from the sprite object as well?

and why do you have to use Bullet.prototype.contructor = Bullet when bullet is already bullet? 


I'm sure these are basic Javascript questions, but it all seems very redundant to me. Is this really how you inherit in Javascript? 

Link to comment
Share on other sites

In traditional JS, objects (e.g., bullet) are instantiated with a constructor function (Bullet) and obtain properties through an object (Bullet.prototype) that is also stored on the constructor.

Custom "classes" must therefore extend both of these aspects:

(1) The constructor invokes the parent constructor

Phaser.Sprite.apply(this, arguments);

and (2) the prototype property is linked to the parent's prototype object.

Bullet.prototype = Object.create(Phaser.Sprite.prototype);

Bullet.prototype.constructor gives all instantiated objects a reference (e.g., bullet.constructor) to the constructor function (Bullet).

Link to comment
Share on other sites

Yes, this is really how you inherit in JS. JS doesn't use classical (i.e. with classes) OO, it uses prototypal (i.e. the "prototype" keyword) OO. That means that you create a real object with real methods and properties and then point other objects at that initial prototype and say "work like that one". Unfortunately we're stuck with JS's clumsy syntax around this; what you're seeing is state-of-the-art inheritance in JS until ES2015 is fully supported everywhere (it introduces a "class" keyword, a "super" keyword, and lets you create class expressions which lets you create mixins which is COOL).


When you call nearly any function in JS by prepending it with the "new" keyword, the JS runtime will create a new object for you (i.e. "{}") and call that function with that object as the context, kinda like this:

var brandNewObject = {};
var myAwesomeThing = myAwesomeFunction.call(brandNewObject);

It'll also pass the arguments you passed to it, but don't worry about that right now. Within the function "myAwesomeFunction", under this context, the value of "this" is that "brandNewObject" guy. Assuming you don't return something from your constructor, that brandNewObject is what is returned. Yes, you can return things from constructors other than the brand new object but don't do that, people will hate you for it.

If you are prototypally inheriting from something else, though, you don't want a blank object. You want a copy of that other prototype. Enter "Object.create". But if you do that, you also want to remind yourself about where this new object came from. So you assign this brand new object that is prototypally linked to its parent a new constructor, i.e. your new one that you just created.

Putting it all together gives you that weird mess up there: make a function. Re-assign its prototype to a copy of something else's prototype. Assign its constructor back to the function you just defined. Happily call "new Whatever" to get more of them.

My resource for all things web is the Mozilla Developer Network. Read up on all this there: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes


Link to comment
Share on other sites

This is what happens when you try and force a pattern into a language that doesn't really support that pattern. The language already changed to make supporting this easier, but has now changed again to introduce `class`, `extends` and `super` which really doesn't help as it papers over what is already a leaky abstraction in JS. However, many developers will learn about OOP and inheritance, get to thinking that discipline is gospel and always structure their code this way, hence its a popular pattern even in the JS world (where it doesn't make as much sense) and it won't be going anywhere.

If you're keen on using mock inheritance in JS then learn the old school method (to get a feel for what the language actually does) then use the newer syntax which will likely feel more comfortable to you. Currently the newer syntax is just sugar but there are potentially some stuff the engine could do with the new syntax (or maybe already does). The newer syntax is supported in all modern browsers, if you're supporting older browsers then you'll need to transpile (which can be a ballache, but is fairly easy to set up and has other advantages too). 

Link to comment
Share on other sites

On 1/26/2017 at 11:16 PM, mattstyles said:

However, many developers will learn about OOP and inheritance, get to thinking that discipline is gospel and always structure their code this way,

So true - I've been using a "true" OOP language in the past (C#) but I've always relied on composition rather than inheritance - it's so much more manageable. 

Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...