Search code examples
javascriptjqueryfunctionfunction-expression

Function expression in JavaScript confusion


I'm trying to make sense of this code from another developer and my JavaScript knowledge is lacking. This function is supposed to take the header menu of a site and convert it into a mobile style menu.

I understand why jQuery is being passed in as $. I don't understand how the variable CPCU is being passed back into itself or why it's being passed back as CPCU || {}. Can someone help me understand how the CPCU variable is working in this situation?

var CPCU = (function (_cpcu, $) {
  'use strict';

  /**
   * Mobile Menu
   */

  var mmenu = _cpcu.Menu.mobile = _cpcu.Menu.mobile || {};
  // Properties.
  mmenu.id = '#mobile-menu';
  mmenu.el = $('');
  mmenu.api = {};
  mmenu.button = '#header-content .menu.button';
  mmenu.aniClass = 'animate';
  mmenu.opts = {
    slidingSubmenus: false
  };
  mmenu.config = {
    classNames: {
      selected: 'active'
    }
  };
  // Methods.
  mmenu.init = function () {
    mmenu.el = $(mmenu.id);
    // Move the active class to from the A to the LI, must happen before mmenu init.
    $('#mobile-menu').find('a.active').parent('li').addClass('active');
    // Now we can init the menu. otherwise it doesn't pick up the active LI.
    mmenu.api = mmenu.el.mmenu(mmenu.opts, mmenu.config).data('mmenu');
    mmenu.button = $(mmenu.button);
    mmenu.button.data('lines', $('.line1,.line2,.line3'));
    mmenu.button.click(function () {
      mmenu.api.open();
    });
    mmenu.api.bind('open', function () {
      mmenu.button.data('lines').addClass(mmenu.aniClass);
    });
    mmenu.api.bind('close', function () {
      mmenu.button.data('lines').removeClass(mmenu.aniClass);
    });
  };
  // Set up doc ready.
  $(document).ready(function () {
    mmenu.init();
  });
  return _cpcu;
})(CPCU || {}, jQuery);

Solution

  • It's attempting to extend an object with more properties/functionality by immediately invoking a function, passing in an object to extend and returning that same object again after extending it.

    First of all, taking CPCU || {}, if CPCU is already defined, it will pass that into the function. If not, CPCU will be falsy, so the right hand side of || is passed in, which is a new empty object. This is then used as the _cpcu parameter inside, and has extra properties etc assigned.

    Using this approach allows you to break up different parts of functionality into different areas, perhaps keeping certain variables private to those areas, or in different files for easier maintainability etc.

    I say "attempting" further up, because this code is actually buggy. If CPCU is indeed undefined by the time this runs, and it passes in {}, then this line:

    var mmenu = _cpcu.Menu.mobile = _cpcu.Menu.mobile || {};
    

    will error, because it can't access the mobile property of the undefined Menu property. So while the developer has used a pattern to break apart different areas of the code, this section actually relies on another section (that defines the Menu property) to have been run before hand, which makes the whole CPCU || {} moot.