Attach a Property
1 2 3 4 5 6 7 8 9
A function is defined. It is instantiated. Later, a new property,
doItRight function, is added to it. Both functions now magically work on the original model instance. We could have attached to
MyModel.prototype and had the
doItRight function attached to all future instantiations of the function as well.
There are a couple great libraries that provide wholesale extension of object properties, just like mixins in other languages. jQuery and Underscore provide
_.extend respectively. They are great utilities that make object extension quick and painless. Here’s an example using Underscore:
1 2 3 4 5 6 7 8 9 10
Handle Per-instance State
Notice that the above methods are very good at attaching functions. The functions in these examples have no shared state. The scenarios that we’ve made up so far haven’t required per-instance state as specified by the mixin. Recently I had a need for all of these things. I was making a library called angular-models.
I wanted to be able to assign what I called
AttributesMixin to any function (Model
classes, written in CoffeeScript). To simplify the story, we have a
set API that assign values to an internal
_attributes object and a
get to retrieve them. These functions were to be assigned to the prototype of the function, but the
_attributes were to be assigned to the object instance only, clean for each new object.
We invented our own convention, where each mixin would optionally implement its own
dependencies function. Each of the
Models knew how to extend itself with a given mixin. This custom extend function was called
@include. As mixins were included, the
dependencies function reference was saved (in an array called
_dependencyFns) and then called in the
Model superclass constructor. So, each
Model subclass is required to call the super constructor to get this functionality.
In the case of
AttributesMixin, it looks as simple as this:
1 2 3 4 5
Model can include like this:
1 2 3 4
Model constructor includes a snippet something like this:
1 2 3
For a more accurate, in-depth look at the code, see the Github repo for angular-models.