Reputation: 13452
I am trying to dig deep into javascript by creating my own MVC library. I am looking into backbone.js source code https://github.com/jashkenas/backbone/blob/master/backbone.js
When you define a Collection in backbone.js you would assign it to a javascript variable like this var AppCollection = Backbone.Collection.extend({ model: BACKBONE_MODEL })
Internally the creator uses underscore and passes the prototype
for the Collection
into underscore's _.extend()
method like this _.extend(Collection.prototype, Events, {})
, where the empty object argument resides in the example I have written is where the author adds all the methods for the Collection object, i.e the model
key which value is the Model object defined earlier in the library.
I am curious, how can I avoid the underscore dependency and add my own prototypical methods for the Collection, specifically how can I pass in an object with the key model
into my own Collection object?
Here is what I have so far.
(function(Pigeon, root, factory) {
root[Pigeon] = factory();
} ('Pigeon', this, function() {
var Pigeon = {};
// Model
var Model = Pigeon.Model = function() {
this.attributes = {};
};
// Collection
var Collection = Pigeon.Collection = function(models) {
};
// View
Pigeon.View = {};
// Controller
Pigeon.Controller = {};
return Pigeon;
}));
Upvotes: 0
Views: 53
Reputation: 3390
To prevent dependency on "_" you can use the following methods to extend an object or class instead of "_.extend()".
Its possible you could use Object.assign for extending the prototypes. The issue with this is it isn't fully supported by all browsers (I'm lookin' at you IE). The other option is to create your own extend function. You could use Object.keys(mixinClass) to do this.
Using Object.assign:
function a() {
this.propOne = "one";
}
a.prototype.methodOne = function() {
document.write("<br/>I am methodOne from a");
}
function b() {
this.propTwo = "two";
}
b.prototype.methodTwo = function() {
document.write("<br/>I am methodTwo from b");
}
function assigned() {
// Call both "super" constructors (order can matter depending on your case)
a.call(this);
b.call(this);
}
// Assign other object properties to your object and set constructor
Object.assign(assigned.prototype, a.prototype, b.prototype);
assigned.constructor = assigned;
var x = new assigned();
document.write("<pre>I am assigned and I look like: \n" + JSON.stringify(x, 2, null) + "</pre>");
x.methodOne();
x.methodTwo();
Using a custom extend function:
function myExtend() {
var args = Array.prototype.slice.apply(arguments);
var target = args.shift();
var extended = {};
args.forEach(function(o) {
Object.keys(o).forEach(function(k) {
extended[k] = o[k];
});
});
Object.keys(extended).forEach(function(k) {
if (!target[k])
target[k] = extended[k];
});
}
function a() {
this.propOne = "one";
}
a.prototype.methodOne = function() {
document.write("<br/>I am methodOne from a");
}
function b() {
this.propTwo = "two";
}
b.prototype.methodTwo = function() {
document.write("<br/>I am methodTwo from b");
}
function assigned() {
a.call(this);
b.call(this);
}
myExtend(assigned.prototype, a.prototype, b.prototype);
assigned.constructor = assigned;
var x = new assigned();
document.write("<pre>I used myExtend and I look like: \n" + JSON.stringify(x, 2, null) + "</pre>");
x.methodOne();
x.methodTwo();
This concept is that of a mixin. You can use this to extend simple objects or to "mixin" multiple classes to create a subclass with methods of multiple types. Unfortunately, this isn't exactly ideal as the object actually has copies of the "supers" properties and methods instead of using references. Either way, this should work for your use case.
Upvotes: 2