Search code examples
backbone.jsrequirejsunderscore.jsamdextending-classes

Extending views in backbonejs with requirejs


So I am using views that are sidebars that have tabs in them, so I created a parent class SidebarView from which I extend two new classes. LeftSidebarView and RightSidebarView. here is the parent class:

define([
  'jquery',
  'underscore',
  'backbone',
  'eventbus'
], function ($, _, Backbone, eventBus) {
  'use strict';
  var SidebarView = Backbone.View.extend({
    tabs: [],
    isHidden: true,
    alignment: '',
    el : '',
    templateId: '',
    milliseconds: 300,

Notice the "tabs: []" array. The two classes that extend from it have only initialize function in them that populates the tabs:

define([
  'jquery',
  'underscore',
  'backbone',
  'views/sidebar',
  'eventbus',
  'views/search'
], function ($, _, Backbone, SidebarView, eventBus, SearchView) {
  'use strict';
  var RightSidebarView = SidebarView.extend({
    alignment: 'right',
    el: "#rightSidebar",
    templateId: '#sidebarTemplate',

    initialize : function() {
      this.tabs['search'] = new SearchView({model: this.model});
    }
  });
  return RightSidebarView;
});

and the other one is:

/*global define*/
define([
  'jquery',
  'underscore',
  'backbone',
  'views/sidebar',
  'views/listings',
  'views/listingDetails',
  'eventbus'
], function ($, _, Backbone, SidebarView, ListingsView, ListingDetailsView, eventBus) {
  'use strict';
  var LeftSidebarView = SidebarView.extend({
    alignment: 'left',
    el: "#leftSidebar",
    templateId: '#sidebarTemplate',

    initialize : function() {
      this.tabs['listings'] = new ListingsView({collection: this.collection);
      this.tabs['listingDetails'] = new ListingDetailsView();
    }
  });

  return LeftSidebarView;
});

In my main.js file I do this:

var leftSidebarView = new LeftSidebarView({collection:listings});
var rightSidebarView = new RightSidebarView({model: searchModel});

What happens is that the leftSideBarView which is an instance of LeftSidebarView and rightSidebarView an instance of RightSidebarView both have 3 members inside of this.tabs. It looks like. I still consider myself a javascript noob so I have got to ask if this is an expected behavior? Why does this happen? I looked at the documentation of _.extend and it says it returns a copy not a reference. So I'm kinda surprised by this happening.

edit: formulated the introduction a bit better and cleaned code a little.


Solution

  • The tabs property are attached to the SidebarView.prototype which means that it is shared between RightSidebarView and LeftSidebarView instances. Everything you send as config options in extend method will override the base class prototype and is shared - like static properties in object oriented languages! That means that you will have to change the implementation to initialize tabs in initialize method like:

    SidebarView:
    initialize : function() {
        this.tabs = [];
    }
    RightSidebarView:
    initialize: function() {
        RighitSidebarView.__super__.initialize.apply(this, arguments);
        // additinal initialization stuff...
    }