0

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;

}));

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

So let me get this straight. Backbone has a class Collection and the class Model is a subclass of the Collection? I am curious about alternative options to achieve this, I am not specifically trying to recreate the _.extend() method. I still havent fully wrapped my head around this pattern, but essentially the Collection class should give me methods to interact with a series of Model classes.
Great answer though, it seems useful, I will read over it until it fully clicks.
I can't speak for what exactly backbone is doing as this is based on what you stated in the OP. Based on it using .extend() it is taking the properties of multiple objects (collections, event, and your object passed) and creating an object with these properties. You can use the options presented to achieve the same goal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.