7
\$\begingroup\$

JavaScript has a class-free object system in which objects inherit properties directly from other objects. This is really powerful, but it is unfamiliar to classically trained programmers. If you attempt to apply classical design patterns directly to JavaScript, you will be frustrated. But if you learn to work with JavaScript's prototypal nature, your efforts will be rewarded.
...
It is Lisp in C's clothing.

-Douglas Crockford

What does this mean for a game developer working with canvas and HTML5? I've been looking over this question on useful design patterns in gaming, but prototypal inheritance is very different than classical inheritance, and there are surely differences in the best way to apply some of these common patterns.

For example, classical inheritance allows us to create a moveableEntity class, and extend that with any classes that move in our game world (player, monster, bullet, etc.). Sure, you can strongarm JavaScript to work that way, but in doing so, you are kind of fighting against its nature. Is there a better approach to this sort of problem when we have prototypal inheritance at our fingertips?

\$\endgroup\$

2 Answers 2

8
\$\begingroup\$

To get decent performance out of JavaScript with modern JS engines one needs to write code that mirrors common structural typing or duck typing patterns. Structural typing is more powerful than providing types only by inheritance but does not really change the design patterns used by games.

As an example, in C++ or Java, where one usually types by inheritance, one usually has deep type hierarchies with several interfaces / virtual classes in order to implement MVC. But games shy away from this kind of design pattern already because it doesn't really help model the kind of data games deal with.

The patterns one does find most useful in game design, like context objects, components, flyweight, or strategy, do not tend to use complicated inheritance hierarchies in the first place, even when implemented in languages like C++. Components involve a single virtual class (at most). Flyweight usually uses C++'s (awkward) structural typing via templates. Strategy often uses some form of type erasure for performance or programmer sanity.

The one exception to this is the prototype pattern itself, which is often found in some form in games, especially for designer-driven data. Using JavaScript makes this pattern trivial. But it is not a particularly difficult pattern to implement, at least poorly, in any language that supports associative data structures. Using JS would let you use it more because you can leverage the underlying engine's optimizer. But I'm not sure if that would really change the way one programs - a naive prototype pattern is already in plenty of places in plenty of games despite its often poor performance.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ I got an upvote less than a minute after posting this, which I refuse to believe is enough time to read it and decide if it is a good answer or not. I have seen several indications that some people are simply upvoting answers that are long and written without horrible grammar. Please don't do that. \$\endgroup\$
    – user744
    Commented Mar 16, 2011 at 22:24
  • \$\begingroup\$ This particular answer just rings true for any experienced developer. I upvoted it almost immediately too, because when I read it I'm like "Yeah, yeah, it always works like this". \$\endgroup\$
    – Nevermind
    Commented Mar 17, 2011 at 6:57
  • \$\begingroup\$ well said! I always felt that JS is very well suited for the kind of data-driven & component approaches that are so common in games but couldn't articulate myself :) \$\endgroup\$
    – oberhamsi
    Commented May 6, 2011 at 7:42
6
\$\begingroup\$

If you really dig into the semantics, you'll find that JavaScript is actually a bit closer to most class-based languages than a "real" prototypal language like Self. The way new works, you almost always create an object that contains state in its own fields and methods in the fields of its prototype. Squint your eyes and that's a class.

To really be prototypal, there'd be no new. You be cloning objects and doing differential inheritance.

So, don't really worry too much about JavaScript's half-prototypal nature. Just understand three pieces:

  1. Most of the time, your objects will essentially be instances of a "class" where the constructor defines its fields and the functions on the constructors prototype define the method.

  2. If you want familiar Java/C#-style single inheritance you can get that by chaining prototypes. Most JS frameworks out there (Closure, dojo, etc.) have some nice helper methods for wiring it up.

  3. You can add methods to any "class" at any time. Feel free to mix in functions onto which ever prototypes need them. You don't always need to set up an inheritance chain and a complex hierarchy. If you have ten classes that need the same method, you can always imperatively add it to those ten classes.

\$\endgroup\$
2
  • \$\begingroup\$ I like the third way of doing things. For example, you could have a "damageable" function that adds a health attribute and a damage() method. You could then duck-type your other code based on the presence of real data/methods instead of sentinel "isDamageable"-type values. \$\endgroup\$
    – drhayes
    Commented Mar 19, 2011 at 9:37
  • 1
    \$\begingroup\$ Exactly right. There are a bunch of JS frameworks that provide "mixins" that do pretty much that: add a bunch of functions to a given prototype. \$\endgroup\$
    – munificent
    Commented Mar 19, 2011 at 19:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .