Jump to content

To prototype or not to prototype


fitness23
 Share

Recommended Posts

I've noticed between a lot of of people's code that there seems to be an even split of people constructing their projects using Javascript prototypes and people who don't. The pain I've experienced using prototypes though is having to use "this." lots. What is everybody's thoughts?

Link to comment
Share on other sites

Really depends on each object and your preferred coding style. If you're experienced with alot of coding languages, it doesn't even register in your mind :lol: the only thing that really matters is whether it works at the end. If using 'this' is painful, I feel bad for you when you hit run-time errors :rolleyes:

Link to comment
Share on other sites

I started Javascript by learning the classical prototype inheritance and I have a hard time switching styles. It really depends on how you like to program. 

For example, my style of programming implemented with Phaser is like so and I know it seems like more work but it's the way I'm currently comfortable with.


//==============================================================================
// State_Boot
//==============================================================================
// 
function State_Boot(){
}

State_Boot.prototype = Object.create(State_Base.prototype);
State_Boot.prototype.constructor = State_Boot;

State_Boot.prototype.init = function() {
  this.input.maxPointers = 1;
  this.stage.disableVisibilityChange = true;
};

State_Boot.prototype.preload = function() {
  this.load.image('preloadBackground', 'img/system/background.png');
  this.load.image('loadbar', 'img/system/loadbar.png');
};

State_Boot.prototype.create = function(){
  this.state.start('Preloader');
};

Then you have the standard Phaser way of prototyping which is very simillar but I have a hard time getting used to this style. I'm still in the testing phase of Phaser so I still may adopt this style.

var BasicGame = {};

BasicGame.Boot = function (game) {
};

BasicGame.Boot.prototype = {

    init: function () {
  this.input.maxPointers = 1;
  this.stage.disableVisibilityChange = true;
    },

    preload: function () {
        this.load.image('preloaderBackground', 'images/preloader_background.jpg');
        this.load.image('preloaderBar', 'images/preloadr_bar.png');
    },

    create: function () {
        this.state.start('Preloader');
    }
};

In the end prototyping makes things easier to manage, and when developing larger games it may be wise to adopt a prototype style, for re-usability and cleaner code, but like I said it's all up to you.

Link to comment
Share on other sites

Just being a pedantic know-it-all: prototypes are part of the language, so you're using them too (Function.prototype, Number.prototype, etc). You might not be making "class like" objects with them, which is fine. The only penalty I know of is if you make lots and lots of objects that look like this:

function makeThing(x, y) {
  return {x: x, y: y,
    someFunction: function() { ... }
  };
}

Every copy of that object is gonna have a copy of "someFunction", too, which is memory inefficient. If you made this using a JS class then all these objects would share the same function. But, of course, you could just not make that function a part of the object and you'd get the same effect. ( =

Other than that I don't know of any inherent benefit you're missing out on, or anything.

Link to comment
Share on other sites

4 hours ago, LTNGames said:

I started Javascript by learning the classical prototype inheritance and I have a hard time switching styles. It really depends on how you like to program. 

For example, my style of programming implemented with Phaser is like so and I know it seems like more work but it's the way I'm currently comfortable with.



//==============================================================================
// State_Boot
//==============================================================================
// 
function State_Boot(){
}

State_Boot.prototype = Object.create(State_Base.prototype);
State_Boot.prototype.constructor = State_Boot;

State_Boot.prototype.init = function() {
  this.input.maxPointers = 1;
  this.stage.disableVisibilityChange = true;
};

State_Boot.prototype.preload = function() {
  this.load.image('preloadBackground', 'img/system/background.png');
  this.load.image('loadbar', 'img/system/loadbar.png');
};

State_Boot.prototype.create = function(){
  this.state.start('Preloader');
};

Then you have the standard Phaser way of prototyping which is very simillar but I have a hard time getting used to this style. I'm still in the testing phase of Phaser so I still may adopt this style.


var BasicGame = {};

BasicGame.Boot = function (game) {
};

BasicGame.Boot.prototype = {

    init: function () {
  this.input.maxPointers = 1;
  this.stage.disableVisibilityChange = true;
    },

    preload: function () {
        this.load.image('preloaderBackground', 'images/preloader_background.jpg');
        this.load.image('preloaderBar', 'images/preloadr_bar.png');
    },

    create: function () {
        this.state.start('Preloader');
    }
};

In the end prototyping makes things easier to manage, and when developing larger games it may be wise to adopt a prototype style, for re-usability and cleaner code, but like I said it's all up to you.

Just to say that the above isn't the "Phaser" way of doing it, it's just standard JavaScript.

There is absolutely no difference between the two approaches above. Both are simply adding functions to an Object prototype. One is extending an already established prototype, while the other is defining it from scratch, but the end result is the exact same. Internally Phaser uses both approaches, depending on if the class is based on an existing Object or not.

I personally always use the second form when coding something from scratch, and when I don't need to inherit from another Object, but only because it's less verbose.

Link to comment
Share on other sites

@rich That is good to know, At first I was getting confused with the "Standard" way, but after getting phaser to work with my style I realized it was the exact same thing. I still may adopt the standard way of prototyping because as you mentioned it is less verbose and looks a bit cleaner, the good thing is I'm still fairly new to Javascript so it should not be hard for me to adapt to writing in a different style and it may help me in the long run. How would you inherit using the "Standard" way? Do you still do the usual Object.create(Phaser.ClassToExtend) ? 

Link to comment
Share on other sites

52 minutes ago, LTNGames said:

@rich That is good to know, At first I was getting confused with the "Standard" way, but after getting phaser to work with my style I realized it was the exact same thing. I still may adopt the standard way of prototyping because as you mentioned it is less verbose and looks a bit cleaner, the good thing is I'm still fairly new to Javascript so it should not be hard for me to adapt to writing in a different style and it may help me in the long run. How would you inherit using the "Standard" way? Do you still do the usual Object.create(Phaser.ClassToExtend) ? 

You have to use Object.create if you want to extend a class (or some other method of transferring functions across). What I meant was that if it was a class that didn't need to extend anything, then I'd use the 2nd method you pasted in your message, just because it's less typing and I prefer the code format - but you could absolutely still use the 1st method posted too. They've both equally valid.

Link to comment
Share on other sites

33 minutes ago, fitness23 said:

Thanks for the responses. I was actually referring to not using prototypes at all vs using them. I noticed that @rich made a boilerplate which doesn't use prototypes at all = https://github.com/DallOner/Phaser-Boilerplate Should this still be used?

That's not my boiler plate, but I see what you mean. Personally I'd say just get used to it. Prototypes are part and parcel of JavaScript. To learn how to use them effectively is useful for JS coding, period, irrespective of using Phaser. Although you may also wish to investigate TypeScript too.

Link to comment
Share on other sites

Just to put the other side of the coin out there...

You don't have to code in an object-oriented way, and you don't have to use prototypes or `this` at all in JS. JS supports many different ways of writing code and it tries to remain neutral about the 'best' way of doing things, largely because the 'best' way is not language dependent, it's based on the interpreter and on developer preference.

Personally I'm not a fan of classical-style inheritance in JS, or the new and this keywords, and I'm not alone, check out the Gorilla/Banana problem. Functional programming is a buzz word in JS right now, but its not some new JS thing, JS has always been built around two fundamental coding paradigms:

* Prototypes

* Functions

And they don't exist in isolation from each other either!

`this` is frequently misleading in JS and even at best it requires you to have knowledge of how the rest of the system works to be used (in most cases), this cognitive load is bad. We generally want to distill complex applications down into smaller and smaller chunks, to make them more manageable, which you can not do if you're carrying around the rest of the system in your brain (again, I could refer to that banana, sans gorilla and jungle please).

Functional programming is a buzz word right now because it tries to address the inherent difficulties of dealing with scope and trying to set up inheritance chains in a loosely typed language. Part of the problem is that everybody's first book on programming involves using functions, but then they pick up the 2nd and 3rd which deal with classical inheritance and they forget that first book because the 2nd and 3rd were so hard to learn and when you've invested a great deal into learning something its a normal human trait to be reticent to ditch it even when its burning you.

Just realised that this sounds perhaps unnecessarily aggressive towards using prototypes (you can't actually avoid them in JS), you need to know many different styles if you want to be a good programmer, just don't get hung up having to write classes or setting up prototype chains in JS, there are other methods, but try to understand the pros and cons of each approach, just saying 'I dont like the way this or that looks' is not a valid argument, neither is 'I prefer this method solely because it is more succinct'.

Link to comment
Share on other sites

functional development has its place, as long as you understand its limitations: especially re: memory management, the cost of closures, and its use in game dev in particular.

Learn it, yes. Embrace it, yes. Just beware the koolaid that flows freely on both sides of this fence.

It's painfully easy to write non-performant code in both functional and 'classical' styles.

Regardless of this, the OP was asking for best practises when working inside Phaser, an entirely prototypal framework. When in Rome ...

Link to comment
Share on other sites

Other thing that could affect your coding style is the kind of editor you are using.

If you are using an editor that supports auto-completion (like VS, Webstorm, SublimeText -with the Phaser plugin-, etc...) then you should take care of your style and provide "static" information via jsdoc and inheritance.

For example, this style:

State_Boot.prototype = Object.create(State_Base.prototype);
State_Boot.prototype.preload = function () { ... };

is "better" than this other style:

State_Boot.prototype = {
  preload: function () { ... }
};

Why? Because in the first style the inference engine "knows" the class is extending a Phaser.State so you can type "this." and a list of methods from the base and current class appears.

But in the second style, the inference engine has not way to know that the prototype is also a Phaser.State, so if you type "this." it shows only a list of Object methods.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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