Backbone.js: Hacker's Guide Part 4
by
at 2012-08-09 07:00:00
original http://feedproxy.google.com/~r/dailyjs/~3/OXMovNe27HQ/mvstar-5
Last week we looked at Backbone’s History and View APIs. We’re coming to the end of this detailed look at Backbone’s internals, but there are still a few interesting things left:
- Backbone’s inheritance implementation
Backbone.sync
Backbone’s inheritance Implementation
The comments indicate that the inherits
function is inspired by goog.inherits
. Google’s implementation is from the Closure Library, but Backbone’s API accepts two objects (incorrectly referred to as a hash) containing “instance” and “static” methods. Each of Backbone’s objects has an extend
method:
Model.extend = Collection.extend = Router.extend = View.extend = extend;
Most development with Backbone is based around inheriting from these objects, and they’re designed to mimic a classical object-oriented implementation.
Backbone uses Underscore’s extend method:
each(slice.call(arguments, 1), function(source) {
for (var prop in source) {
obj[prop] = source[prop];
}
});
return obj;
This isn’t the same as ES5’s Object.create, it’s actually copying properties (methods and values) from one object to another. Since this isn’t enough to support Backbone’s inheritance and class model, the following steps are performed:
- The instance methods are checked to see if there’s a
constructor
property. If so, the class’s constructor is used, otherwise the parent’s constructor is used (i.e.,Backbone.Model
) - Underscore’s
extend
method is called to add the parent class’s methods to the new child class - The
prototype
property of a blank constructor function is assigned with the parent’s prototype, and a new instance of this is set to the child’sprototype
property - Underscore’s
extend
method is called twice to add the static and instance methods to the child class - The child’s prototype’s constructor and a
__super__
property are assigned
This pattern is also used for classes in CoffeeScript, so Backbone classes are compatible with CoffeeScript classes.
Update: Jeremy Ashkenas clarified this process on Twitter:
… it’s just your basic prototype chain, plus one extra goodie: any constructor properties (static) are copied over as well.
Backbone’s Sync API
The Backbone.sync method is intended to be overridden to support other backends. The built-in method is tailed to a certain breed of RESTful JSON APIs – Backbone was originally extracted from a Ruby on Rails application, which uses HTTP methods like PUT
the same way.
The way this works is the model and collection classes have a sync
method that calls Backbone.sync
. Both will call this.sync
internally when fetching, saving, or deleting items.
The sync
method is called with three parameters:
method
: One ofcreate
,update
,delete
,read
model
: The Backbone model objectoptions
: May include success and error methods
Implementing a new sync
method can use the following pattern:
Backbone.sync = function(method, model, options) {
var requestContent = {}, success, error;
function success(result) {
// Handle results from MyAPI
if (options.success) {
options.success(result);
}
}
function error(result) {
// Handle results from MyAPI
if (options.error) {
options.error(result);
}
}
options || (options = {});
switch (method) {
case 'create':
requestContent['resource'] = model.toJSON();
return MyAPI.create(model, success, error);
case 'update':
requestContent['resource'] = model.toJSON();
return MyAPI.update(model, success, error);
case 'delete':
return MyAPI.destroy(model, success, error);
case 'read':
if (model.attributes[model.idAttribute]) {
return MyAPI.find(model, success, error);
} else {
return MyAPI.findAll(model, success, error);
}
}
};
This pattern delegates API calls to a new object, which could be a Backbone-style class that supports events. This can be safely tested separately, and potentially used with libraries other than Backbone.
There are quite a few sync implementations out there: