Backbone.js, Spine.js extend and inheritance
Blogs20142014-11-08
Backbone.js, Spine.js extend and inheritance
Backbone use extend() to set up the prototype chain, e.g.:
- Backbone.Model.extend(instanceProperties, [classProperties]);
- Backbone.View.extend(instanceProperties, [classProperties]);
Spine.js use include() and extend() to the same thing. e.g.:
- var User = Spine.Class.create();
- User.include(instanceProperties)
- User.extend(classProperties)
- var Book = Spine.Class.create(instanceProperties, [classProperties]);
Here I list the implementation of 2 of them, for comparison and reference.
Backbone.js extend function
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent's constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function.
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
return child;
};Spine.js include and extend function
var moduleKeywords = ["included", "extended"];
var Class = Spine.Class = {
inherited: function(){},
created: function(){},
prototype: {
initialize: function(){},
init: function(){}
},
create: function(include, extend){
var object = Object.create(this);
object.parent = this;
object.prototype = object.fn = Object.create(this.prototype);
if (include) object.include(include);
if (extend) object.extend(extend);
object.created();
this.inherited(object);
return object;
},
init: function(){
var instance = Object.create(this.prototype);
instance.parent = this;
instance.initialize.apply(instance, arguments);
instance.init.apply(instance, arguments);
return instance;
},
proxy: function(func){
var thisObject = this;
return(function(){
return func.apply(thisObject, arguments);
});
},
proxyAll: function(){
var functions = makeArray(arguments);
for (var i=0; i < functions.length; i++)
this[functions[i]] = this.proxy(this[functions[i]]);
},
include: function(obj){
for(var key in obj)
if (moduleKeywords.indexOf(key) === -1)
this.fn[key] = obj[key];
var included = obj.included;
if (included) included.apply(this);
return this;
},
extend: function(obj){
for(var key in obj)
if (moduleKeywords.indexOf(key) === -1)
this[key] = obj[key];
var extended = obj.extended;
if (extended) extended.apply(this);
return this;
}
};