3

I have a backbone model

var app = app || {};

app.Era = Backbone.Model.extend({

    defaults: {
        from: Number.NEGATIVE_INFINITY,
        until: Number.POSITIVE_INFINITY,
        stash: {
            from: null,
            until: null
        },
        _enabled: true
    },

    toggle: function(){
        if(this.get('_enabled')){
            this.disable();
        }else{
            this.enable();
        }

        this.save();
    },

    enable: function(){
        this.from = this.stash.from;
        this.until = this.stash.until;

        this.stash.from = null; // strictly speaking unnecssary
        this.stash.until = null;

        this._enabled = true;
    },

    disable: function(){
        this.stash.from = this.from;
        this.stash.until = this.until;

        this.from = null;
        this.until = null;

        this._enabled = false;
    },

    enabled: function(){
        return this._enabled;
    },

});

which I'm trying to extend like so

Name = app.Era.extend({ defaults: { value: '' } });

This seems to work, I get no error in the console. I can even instantiate a new Name, but when I try to instantiate a new Name, I get an Error message:

> era = new app.Era()
child
> era.get('from')
-Infinity
> Name = app.Era.extend({ defaults: { value: '' } })
function (){ return parent.apply(this, arguments); }
> name = new Name()
child
> name.get('value')
TypeError: Object [object Object] has no method 'get'

I'd be grateful of some feedback!

lowerkey
  • 8,105
  • 17
  • 68
  • 102

2 Answers2

10

Edit: This might very well be a decent answer, but not to this particular question... The correct answer was provided by Bryan Clark. I'll leave this here regardless, because while I misunderstood your question, it describes a solution to a common problem and may help you anyway.

Backbone inheritance works by modifying the constructor function's prototype. When you extend a model and redefine the defaults property, it doesn't merge the Name.defaults property to Era.defaults, but simply hides it.

Consider a simplified example:

var Era = Backbone.Model.extend({ name: "Era" });
var Name = Era.extend({ name: "Name" });
console.log(new Name().name); //-> "name", makes sense, right?

To merge the derived class defaults to the superclass's, you can take advantage of the fact that Model.defaults can be defined as a function as well as an object literal.

var Era = Backbone.Model.extend({ 
  defaults: {
    //..
  } 
});

var Name = Era.extend({ 
  //define defaults as a function
  defaults: function() {
    //copy the superclass defaults into a new object, and
    //then extend that with the new defaults
    return _.extend({}, Era.prototype.defaults, {
      value:''
    });
  }
});
jevakallio
  • 35,324
  • 3
  • 105
  • 112
  • 3
    Hmm.. It seems that I read your question poorly. My answer doesn't actually explain why you would be getting the error you are getting in the console. I thought it was a different error. I'll leave this here regardless, and I'll try to pop by later to amend it, if I can think of why you are experiencing that error. Sorry about the confusion! – jevakallio Jan 30 '13 at 22:22
3

You can't use name in that context, you're running into window.name. If you start from scratch without the lowercase name variable you should run just fine. Also, fencliff makes good points in how to use default inheritance.

Bryan Clark
  • 2,542
  • 1
  • 15
  • 19