1

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);
Sarath Chandra
  • 1,850
  • 19
  • 40
Anne Lee
  • 107
  • 1
  • 8
  • Look at this related question: [What does “var FOO = FOO || {}” (assign a variable or an empty object to that variable) mean in Javascript?](http://stackoverflow.com/questions/6439579/what-does-var-foo-foo-assign-a-variable-or-an-empty-object-to-that-va) – Tobías Apr 20 '16 at 14:53

2 Answers2

4

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.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
  • 1
    Yes that's a good point: code written with the pre-initialization "guard" pattern should actually work :) – Pointy Apr 20 '16 at 14:55
1

The parameter CPCU || {} is there to account for the possibility that prior to the var CPCU declaration at the top of the code you posted, some other code may have already initialized CPCU. The pattern is a common one.

Thus, if CPCU is not defined (probably the common case, though I don't know much about your software of course), then the value passed to the anonymous function will be the new empty object ({}). However, if CPCU is already defined and initialized, then its current value will be passed instead.

Thus, hypothetically, if on some page there's a different script that's imported via a <script> tag before the code you posted, and it does something like:

var CPCU = { debug: true };

then when the code you posted is run, it will see that CPCU already has a value. This is generally done to add flexibility and account for unforseen possibilities.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • So does this code have to be called somewhere else for this function to run? And if so, do you know what that function call would look like? – Anne Lee Apr 20 '16 at 14:58
  • 1
    @AnneLee I don't understand the question. The code you posted is self-contained and doesn't need to be "called". However, as James Thorpe points out in the other answer, *something* has to pre-initialize that `CPCU` object, or else the code posted here will throw an exception when it runs. I have no idea what that other code might look like other than that it'd involve the symbol `CPCU`. – Pointy Apr 20 '16 at 15:04
  • Oh, I see...that makes sense. Thanks a lot! – Anne Lee Apr 20 '16 at 15:06