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
constructorproperty. If so, the class’s constructor is used, otherwise the parent’s constructor is used (i.e.,Backbone.Model) - Underscore’s
extendmethod is called to add the parent class’s methods to the new child class - The
prototypeproperty of a blank constructor function is assigned with the parent’s prototype, and a new instance of this is set to the child’sprototypeproperty - Underscore’s
extendmethod 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,readmodel: 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: