emberjs mixin

emberjs has mixin feature which allows code reuse and keep code modular. It also support _super() method.

mixin using apply

m = Ember.Mixin.create({
  skill: function() {
    return 'JavaScript & ' + this._super()
  }
});
main = { skill: function(){ return 'Ruby' }}
o  = m.apply(main);
console.log(o.skill());

result: JavaScript & Ruby

mixin in create and extend

Now lets see usage of mixin in create and extend. Since create and extend work similarly I am only going to discuss create scenario .

skillJavascript = Ember.Mixin.create({
  skill: function() { return 'JavaScript '}
});
main = { skill: function() { return 'Ruby & ' + this._super(); } }
p = Ember.Object.create(skillJavascript, main )
console.log(p.skill())

result: Ruby & JavaScript

Notice that in the first case the mixin code was executed first. In the second case the mixin code was execute later.

Here is how it works

Here is mergeMixins code which accepts the mixins and the base class. In the first case the mixins list is just the mixin and the base class is the main class.

At run time all the mixin properites are looped through. In the first case the mixin m has a property called skill .

m.mixins[0].properties.skill

function () {
    return 'JavaScript & ' + this._super()
  }

Runtime detects that both mixin and the base class has a property called skill . Since base class has the first claim to the property a call is made to link the _super of the second function to the first function.

That works is done by wrap function.

So at the end of the execution the mixin code points to base code as _super.

It reveres itself in case of create

In the second case the mixin skillJavaScript and the main are the mixins to base class of Class. The mixin is the first in the looping order. So the mixin has the first claim to key skill since it was unclaimed by base class to begin with.

Next comes the main function and since the key is already taken the wrap function is used to map _super of main to point to the mixin .

Remember in Create and Extend it is the last one that executes first

Here is an example with two mixins.

skillHaskell = Ember.Mixin.create({
  skill: function() { return 'Haskell' }
});
skillJavascript = Ember.Mixin.create({
  skill: function() { return 'JavaScript & ' + this._super() }
});
p = Ember.Object.create(skillHaskell, skillJavascript, { skill: function(){ return 'Ruby & ' + this._super(); } } )
console.log(p.skill())

result: Ruby & JavaScript & Haskell

In this case the haskell mixin firt claimed the key. So the javascript mixin’s _super points to haskell and the main code’s _super points to Javascript.

Embjers makes good use of mixin

emberjs has features like comparable, freezable, enumerable, sortable, observable. Take a look at this to checkout their code.