emberjs has mixin feature which allows code reuse and keep code modular. It also support _super() method.
mixin using apply
1m = Ember.Mixin.create({ 2 skill: function () { 3 return "JavaScript & " + this._super(); 4 }, 5}); 6main = { 7 skill: function () { 8 return "Ruby"; 9 }, 10}; 11o = m.apply(main); 12console.log(o.skill()); 13 14result: 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 .
1skillJavascript = Ember.Mixin.create({ 2 skill: function () { 3 return "JavaScript "; 4 }, 5}); 6main = { 7 skill: function () { 8 return "Ruby & " + this._super(); 9 }, 10}; 11p = Ember.Object.create(skillJavascript, main); 12console.log(p.skill()); 13 14result: 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 properties are looped through. In the first case the mixin m has a property called skill .
1m.mixins[0].properties.skill 2 3function () { 4 return 'JavaScript & ' + this._super() 5 }
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.
1skillHaskell = Ember.Mixin.create({ 2 skill: function () { 3 return "Haskell"; 4 }, 5}); 6skillJavascript = Ember.Mixin.create({ 7 skill: function () { 8 return "JavaScript & " + this._super(); 9 }, 10}); 11p = Ember.Object.create(skillHaskell, skillJavascript, { 12 skill: function () { 13 return "Ruby & " + this._super(); 14 }, 15}); 16console.log(p.skill()); 17 18result: Ruby & JavaScript & Haskell;
In this case the haskell mixin first 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 (Link is not available) to checkout their code.