What are "mixins" in JavaScript?

11

What are "mixins"?

I see in some JavaScript codes and would like to know what it is; actual examples of usage.

    
asked by anonymous 31.07.2014 / 00:16

2 answers

10

Mixin in JavaScript is a class designed with a focus on DRY . It gives the developer the ability to take shortcuts to solve problems, almost like the famous "helpers", with the difference that a mixin can refer to or be referenced by a module 1 without the direct extension or inheritance.

A practical and useful example

Buttons ( <button> ) and anchors ( <a> ) are conceptually components of the DOM , which means that when / if we speak of "components", we are going in the synthesis of the business; going in the most generic layer of elements that our favorite markup language works on.

On the whole, components are renderable materials; are items that when checked in your HTML have the ability to invoke for user viewing and materialization of the interface.

So, I sampled the mixin in this scenario, through JavaScript. Using buttons and anchors still, I developed the following objects:

var Button = {
    design: {
        colors: {
            background: 'blue',
            text: 'yellow'
        },
        borderRadius: 3,
        padding: 5,
    },
    shape: function () {
        return '<button style="background-color:' + this.design.colors.background + ';'
                + 'border-radius:' + this.design.borderRadius + 'px;'
                + 'padding:' + this.design.padding + 'px;'
                + 'color:' + this.design.colors.text + ';'
                + 'border: none;">'
                + this.getContent()
                + '</button>';
    }
};

and

var Anchor =  {
    design: {
        color: 'green',
        underline: true
    },
    destination: 'google.com',
    shape: function () {
        return '<a style="color:' + this.design.color + ';'
                + 'text-decoration:' + (this.design.underline ? 'underline' : 'none') + ';" '
                + 'href="http://' + this.destination + '">'
                + this.getContent()
                + '</a>';
    }
};

They have features in common, right? design and shape are examples. However, if you pay attention, they are differentiated by their implementation; by its particular characteristics. In other words, each of these "components" has its own personality, such as the marking itself, which in the case of the button is <button> and in case the anchor is <a> .

Remembering ...

Remember that I just talked about "rendering"? Of course, components like these should have the ability to manifest in the DOM. So would we teach the two objects ( Button and Anchor ) to project without repeating to create equal methods in their scopes? Mixins!

See this third object I drew:

var Component = {
    render: function (platform) {
        $(platform).html(this.shape());
    },
    append: function (platform) {
        $(platform).append(this.shape());
    },
    setContent: function (content) {
        this.content = content;
        return this;
    },
    getContent: function () {
        return this.content;
    }
};

It, in turn, has features that can make our buttons and anchors useful - and we can freely use it by cloning its scope between our two objects.

For cloning, I used the extend() method of Underscore.js :

_.extend(Anchor, Component);
_.extend(Button, Component);

The result was simple. To render our components, we would then do the following:

Button
    .setContent('Register')
    .append('body');

Anchor
    .setContent('And here if you already have an account!')
    .append('body');

If we put everything together, the result will be this:

var Component = {
    render: function (platform) {
        $(platform).html(this.shape());
    },
    append: function (platform) {
        $(platform).append(this.shape());
    },
    setContent: function (content) {
        this.content = content;
        return this;
    },
    getContent: function () {
        return this.content;
    }
};

var Button = {
    design: {
        colors: {
            background: 'blue',
            text: 'yellow'
        },
        borderRadius: 3,
        padding: 5,
    },
    shape: function () {
        return '<button style="background-color:' + this.design.colors.background + ';'
                + 'border-radius:' + this.design.borderRadius + 'px;'
                + 'padding:' + this.design.padding + 'px;'
                + 'color:' + this.design.colors.text + ';'
                + 'border: none;">'
                + this.getContent()
                + '</button>';
    }
};

var Anchor =  {
    design: {
        color: 'green',
        underline: true
    },
    destination: 'google.com',
    shape: function () {
        return '<a style="color:' + this.design.color + ';'
                + 'text-decoration:' + (this.design.underline ? 'underline' : 'none') + ';" '
                + 'href="http://' + this.destination + '">'
                + this.getContent()
                + '</a>';
    }
};

_.extend(Anchor, Component);
_.extend(Button, Component);

Button
    .setContent('Register')
    .append('body');

Anchor
    .setContent('And here if you already have an account!')
    .append('body');

To play and practice, here is jsFiddle .

1: a living class from your typed application in / with JavaScript;

    
31.07.2014 / 17:14
5

Mixins is a very common term in object-oriented programming languages, in javascript the MooTools library is perhaps the best reference.

The basic idea behind the creation and use of mixins is the DRY concept that means "Dont Repeat Yourself."

A mixin is, for example, an object where you define functions / methods that can then be imported into other objects, namespaces, or classes. If in your code you have some methods that are accurate in different pieces of code you can define those methods in a separate object and import / mix them (mixin) in your objects. So when you need to fix this block of code you just have to do it in one place.

Here is an example of using Mixin in MooTools Classes: Source: Keetologi, Mark Keeto, one of the founders of MooTools

var Ringer = new Class({

    sound: 'ring.ogg',

    ring: function(sound){
        sound = sound || this.sound;
        new Sound(sound).play();
    }

});

var Phone = new Class({

    Implements: Ringer,

    initialize: function(number){
        this.number = number;
        this.sound = 'phone.ogg';
    },

    call: function(from){
        this.ring();
        new Notification('Call from ' + this.from);
    }

});

var AlarmClock = new Class({

    Implements: Ringer,

    initialize: function(alarmTime){
        this.time = alarmTime;
        this.sound = 'alarm.ogg';
    },

    alarm: function(time){
        if (time == this.time) {
            this.ring();
            new Notification('Wake up sleepy head!');
        }
    }

});

In this example above, both the "Phone" and "Alarm" Class have common code. The best solution, instead of placing exactly the same code within each Class, is to make a Class apart and then import it into the Classes in which it is needed. In MooTools this method of importing "Mixins" is called "Implement".

    
31.07.2014 / 17:13