Vilius Paulauskas
Vilius Paulauskas

Reputation: 3261

Unexpected constructor / extend behavior in BackboneJS

Got really confused on how JavaScript/BackboneJS works. Let's consider the following example:

window.MyView = Backbone.View.extend({
    index: 0,
    list: [],        
    initialize: function () {
        console.log("Initializing MyView");
        console.log("this.index = " + this.index);
        console.log("this.list = [" + this.list.join(',') + "]");
        this.index++;
        this.list.push(this.index);
    }
});

var first = new MyView(),
    second = new MyView();

What I was expecting here is that new MyView() will create a clean copy of window.MyView "class", so the outbut would be:

Initializing MyView
this.index = 0
this.list = []

Initializing MyView
this.index = 0
this.list = []

But instead I've got

Initializing MyView
this.index = 0
this.list = []

Initializing MyView
this.index = 0
this.list = [1] // Very unexpected!

The confusing part is that integer variable "index" was in fact 0 as expected, but array "list" already contained a value from previous initialization. How come is this way?

Demo http://jsfiddle.net/fqZTp/3/

Upvotes: 1

Views: 100

Answers (1)

Rob Hruska
Rob Hruska

Reputation: 120286

The different behavior between what happens to list and index is explained well with these two answers:

To summarize them:

  • list and index both exist on MyView's prototype.
  • After creating your new MyView(), initialize() operates in the context of the newly created instance (i.e. not the prototype).
  • When you push() something onto list, you're pushing it onto the list object that's referenced by the prototype. You're not updating the reference to the list at all, just reading it.
  • When you index++, this actually does an assignment (this.index = this.index + 1) behind the scenes. When you assign something to an object, it doesn't matter whether or not it exists on the prototype - you are assigning it to that particular instance. The prototype does not change.

For the behavior you're expecting, just set both properties in your initialize function:

window.MyView = Backbone.View.extend({
    initialize: function () {
        this.index = 0;
        this.list = [];

        this.index++;
        this.list.push(this.index);
    }
});

Upvotes: 3

Related Questions