---
title: Two gotchas every CoffeeScript and Backbone.js developer should know
teaser: How mutation can lead you down the wrong path.
tags: web,javascript
author: Sage Griffin
published_on: 2013-05-21
---

If you're a Ruby developer working with Rails, at some point you're going to
need to work with JavaScript. While the two languages have many similarities,
the fundamental differences in their object models can be quite jarring.
CoffeeScript helps to provide a more Ruby-like syntax, but if you’re not careful
you can introduce bugs to your code in surprising ways.

Let's look at an example. Let's say we have an expensive operation, and need to
cache the result. In CoffeeScript, we might write the this code as:

    class GiantRobot
      smashCache: {}

      smashInto: (other) =>
        @smashCache[other] ||= @expensiveCalculations(other)

However, this code leads to a surprising problem when we start smashing things
together.

    ralph = new GiantRobot()
    voltron = new GiantRobot()

    ralph.smashInto(optimusPrime)   # => not cached
    ralph.smashInto(optimusPrime)   # => cached
    voltron.smashInto(optimusPrime) # => cached?!

To see why this occurs, we need to take a look at how objects work in
JavaScript. Unlike Ruby, JavaScript has no concept of classes. Instead it
constructs its objects using prototypes. If you're writing your code in
CoffeeScript, you can almost always ignore this fact, and write your code as if
you were in Ruby or Python. In this case, however, CoffeeScript is making our
problem less apparent, so let's take a look at what this code looks like using
plain JavaScript.

    function GiantRobot() {}

    GiantRobot.prototype.smashCache = {};

    GiantRobot.prototype.smashInto = function(other) {
      if (!this.smashCache[other]) {
        this.smashCache[other] = this.expensiveCalculations(other);
      }
      return this.smashCache[other];
    };

Specifically, our problem stems from the fact that setting `smashCache` on the
prototype may not work the way you'd think.

## How prototypes work

When we create `ralph` with, `ralph` technically has no `smashCache` property.
When we do `this.smashCache`, JavaScript looks for that property on `ralph`,
followed by `ralph`'s prototype, then `ralph`'s prototype's prototype, and so forth
until it finds something that has the `smashCache` property.

JavaScript provides us a way to see this in action, using the `hasOwnProperty`
method.

    ralph.hasOwnProperty('smashCache')                # => false
    GiantRobot.prototype.hasOwnProperty('smashCache') # => true

So when we call `this.smashCache`, we are always getting back
`GiantRobot.prototype.smashCache`, which means when we mutate it, we are
mutating the same instance of `smashCache` that is used by every instance of
`GiantRobot`. This is only an issue when we're talking about arrays and objects.

    ralph.smashCache = 'some value'
    # Variable assignment sets the property directly on the instance
    ralph.hasOwnProperty('smashCache') == true

## Avoiding mutating the prototype

So how do we get around this? Ironically, the answer is simply to make our
original example look more like our Ruby code.

    class GiantRobot
      constructor: ->
        @smashCache = {}

Now each instance will have it's own separate smashCache, and all is well with the
world.

## Backbone.js gotcha: Mutating the defaults object

A similar problem exists in Backbone.js when using the defaults object on your
models.

    class RobotProfile extends Backbone.Model
      defaults:
        images: []

      addImage: (newImage) ->
        @get('images').push(newImage) # => Mutates a shared instance

The solution for this problem is even simpler. If we change the defaults
property to be a function that returns the same hash, Backbone will call it
every time a new instance is created.

    class RobotProfile extends Backbone.Model
      defaults: ->
        images: []

Now our images array will no longer be shared across multiple instances, and we
can mutate to our heart's content.
