As we saw in the above examples, JavaScript objects can inherit properties from other objects. The inherited object can also inherit properties and behavior from other objects, thus forming an inheritance chain. While sometimes it makes sense to represent the object hierarchy in terms of their natural order, but a lot of other times it also becomes messy and unmanageable to handle long inheritance chains. Thankfully, when it comes to alternatives for function reuse, JavaScript makes it possible to implement the mixin reuse design pattern.
In computer science, a mixin is a class, which contains the behavior for a particular type (shape, color, person). Mixins are supposed to contain the behavior, or verbs, rather than the properties, or nouns. They are considered to be abstract, which means that they are not intended to be instantiated on their own, but they are supposed to lend or copy their methods or behavior to the borrowing class. Using mixins can be thought of as using composition, rather than inheritance.
Ember.js makes it really easy to implement and use this design pattern. Ember CLI follows the convention of putting the mixins in the app/mixins/
directory of your project.
Let's create two mixins, a focusable mixin and a number validator mixin present in the app/mixins/
directory. The code for this example can be found inside chapter-2/example4/
directory:
import Ember from 'ember'; export default Ember.Mixin.create({ valid: function(number){ if(isNaN(number)){ return false; }else{ return true; } } });
The contents of valid_number.js are present in chapter-2/example4/app/mixins/valid_number.js
import Ember from 'ember'; export default Ember.Mixin.create({ onFocus: function(){ console.log("do something creative on focus"); } });
The contents of focusable.js are present in chapter-2/example4/app/mixins/focusable.js
App.NumericTextBox = Ember.Object.extend(App.ValidNumberMixin,App.FocusableMixin,{ text:"" }); var textbox = App.NumericTextBox.create(); console.log(textbox.valid("12")); //true textbox.onFocus(); //do something creative on focus
As you can see that we define a new mixin in Ember.js using the Ember.Mixin.create
statement, Ember.Mixin
class serves as a base for all the mixins you would be creating in your Ember.js application. Since Ember.Mixin
class cannot extend other mixins, there is no extend
method on the Ember.Mixin
class. There is only a create
method that is used to instantiate the Ember.Mixin
class with the supplied behavior.
After we have defined two mixin instances, validNumberMixin
and focusableMixin
, each having their own functionality; lets create the numerictBox
object that includes the above two mixins.
import Ember from 'ember'; import validNumberMixin from './mixins/valid_number'; import focusableMixin from './mixins/focusable'; export default Ember.Object.extend(validNumberMixin,focusableMixin,{ text:"" });
The contents of numeric_box.js are present in chapter-2/app/numeric_box.js
Here, you can see that we have exported an object that extends from Ember.Object
in our file. Since the mixins are not available by default to our module, we will have to import them explicitly using the import
keyword.
As we discussed earlier, the extend
method present in Ember.Object
also takes in optional arguments of Ember.Mixin
type. By including these mixins, we are copying the behavior present in the mixins to our validNumberMixin
definition. Thus, calling valid
and onFocus
on the instance of numericBox
, should work as expected.
Let's now call the numericBox
from app/app.js
, in order for our code to run when the application initializes:
import numbeicBox from './numeric_box'; var textbox = numbeicBox.create(); console.log(textbox.valid("12"));//true textbox.onFocus();// do something creative on focus"
Mixins provide a very interesting alternative to simplifying your JavaScript inheritance chain. This pattern makes it easy when you want to inherit properties from more than once source, thus simplifying your code bases while keeping functionality in independent testable units.
3.137.220.92