IIFEs, Mixins, and Modules in JavaScript Objects

Refactoring ugly code into pretty code

Wikipedia describes a mixin in general terms as so:

In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes.

In this particular part of OOP part of the freeCodeCamp course I am taking, they are going over IIFEs, objects, mixins, and what they call modules. One of the lessons has the student refactor two given mixins into a IIFE that returns an object--i.e. a module.

Per FCC, "The advantage of the module pattern is that all of the motion behaviors can be packaged into a single object that can then be used by other parts of your code."

Note: The focus of this post is not IIFEs (though they are interesting!)

Non-module mixins

This is the code provided by FCC in their lesson. The intent of the lesson is to have the student refactor the below mixins into an IIFE that returns an object of mixins.

// Provided by FCC
let isCuteMixin = function(obj) {
  obj.isCute = function() {
    return true;
  };
};
let singMixin = function(obj) {
  obj.sing = function() {
    console.log("Singing to an awesome tune");
  };
};

Mixins, modularized (via function declarations)

Below is one version of the code that passes their refactorization challenge. It uses function declarations. It is largely based on an example provided by FCC in their lesson.

  1. It is objectively ugly

  2. It is overly verbose

  3. Note how the top-level return returns an object.

let funModule = (function () {
  return {
    isCuteMixin: function(obj) {
      obj.isCute = function() {
        return true;
      };
    },
    singMixin: function(obj) {
      obj.sing = function() {
        console.log("Singing to an awesome tune");
      };
    }
  }
})();

Mixins, modularized! (via ES6 arrow functions)

The below code is the code above, just further refactored to remove all function declarations. This code also passes their refactorization challenge.

It uses ES6 arrow functions and implicit return where appropriate.

  1. It is not ugly

  2. It is more concise

let funModule = (() => {
  return {
    isCuteMixin: obj => {
      obj.isCute = () => true;
    },
    singMixin: obj => {
      obj.sing = () => console.log("Singing to an awesome tune");
    }
  }
})();

Important differences

In both refactorizations, important differences are as follows:

  1. The comma between isCuteMixin and singMixin as methods

  2. The : instead of the = as to defining the methods' logic

  3. The lack of let as to both isCuteMixin and singMixin

Seeing them side by side as a diffing is probably most helpful!