chris Frisina
chris Frisina

Reputation: 19688

Instantiation of an object vs function in Backbone,js

I have taken over a research project, and have been doing pretty well, except recently, I think I am misunderstanding some JS structure that is implemented in Backbone. I am confused as to the structure of a model or collection, and whether it returns an object or a function.

The project has this current structure for models:

define([…], function(…) {
  var measureModel = Backbone.Model.extend({
    defaults: {…},
    initialize: function(){…}
    …
  });
  return measureModel; //here there is no function, so I assume its an object
});

and for collections:

define([…], function(…){
  var measuresCollection = Backbone.Collection.extend({
    model: measureModel,
    initialize: function(){…}
  });
  return new measuresCollection(); //here I assume it is an function
});

I have made new models and collections with the above structure, but got the errors below, so I also tried this:

define([…], function(…){
  return Backbone.Collection.extend({  // here I just return the Object
    model: newerModel,
    initialize: function(){…}
  });
});

Following this first structure, on some new models and collections, I am getting the errors Uncaught TypeError: object is not a function or Uncaught TypeError: [Object object] is not a function or Uncaught TypeError: undefined is not a function, depending on omission of the ending return statement, or just returning the object outright.

I am calling the constructor in another View like so: this.newerCollection = new NewerCollection();

Upvotes: 2

Views: 237

Answers (1)

freejosh
freejosh

Reputation: 11383

extend always returns a function, which is used as a constructor for the Model/Collection/View you've extended.

In this code block (the first one in the question), you're returning a function, which is the constructor for the extended Model:

define([…], function(…) {
  var measureModel = Backbone.Model.extend({
    defaults: {…},
    initialize: function(){…}
    …
  });
  return measureModel; //here you are returning a function, which is a constructor for the extended Model
});

In this code block (the second one in the question), you're returning an object, not a function, because you've instantiated a measuresCollection using new. The measuresCollection variable itself is the constructor:

define([…], function(…){
  var measuresCollection = Backbone.Collection.extend({
    model: measureModel,
    initialize: function(){…}
  });
  return new measuresCollection(); //here you are returning an object because it is instantiated using `new`
});

If you try to use the value of that module to instantiate a new object you'll get the "object is not a function" error.

In this code block (the third block in the question) would be equivalent to returning measuresCollection in the second block. There, you're returning a function and not an object, the same way as the first block is.

define([…], function(…){
  return Backbone.Collection.extend({  // this is returning a function, the same as the first code block
    model: newerModel,
    initialize: function(){…}
  });
});

If you omit the return statement from your module, it returns undefined and you'll get the "undefined is not a function" error when you try to use it to instantiate an object.

There is essentially no difference between the way you return the constructors in the 1st and 3rd code blocks. The former simply assigns the constructor to a local variable before returning it. The only reason to do it is if you need to manipulate it before returning it.

Upvotes: 4

Related Questions