JavaScript 混乱中的函数表达式

Function expression in JavaScript confusion

我正试图从另一位开发人员那里理解这段代码,但我的 JavaScript 知识不足。此函数应该采用站点的 header 菜单并将其转换为移动样式菜单。

我理解为什么 jQuery 被传递为 $。我不明白变量 CPCU 是如何传回自身的,或者为什么它会作为 CPCU || {} 传回。有人可以帮助我了解 CPCU 变量在这种情况下是如何工作的吗?

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);

参数 CPCU || {} 是为了说明在您发布的代码顶部的 var CPCU 声明之前,一些 other 的可能性代码可能已经初始化 CPCU。图案很普通。

因此,如果 CPCU 定义 (可能是常见情况,当然我对您的软件了解不多),则传递的值匿名函数将是新的空对象 ({})。但是,如果 CPCU 已经定义和初始化,那么它的当前值将被传递。

因此,假设在某个页面上有一个不同的脚本是通过 <script> 标签在您发布的代码之前导入的,它会执行类似以下操作:

var CPCU = { debug: true };

然后当您发布的代码是 运行 时,它会看到 CPCU 已经有一个值。这样做通常是为了增加灵活性并考虑不可预见的可能性。

它试图通过立即调用一个函数、传入一个对象来扩展并在扩展后再次返回同一个对象来扩展一个对象properties/functionality。

首先,取 CPCU || {},如果 CPCU 已经定义,它将把它传递给函数。如果不是,CPCU会是falsy,所以传入||右边,就是一个新的空对象。然后将其用作内部的 _cpcu 参数,并分配了额外的属性等。

使用这种方法可以将功能的不同部分分解到不同的区域,也许将某些变量保留为这些区域的私有,或者在不同的文件中以便于维护等。

我说"attempting"更进一步,因为这段代码实际上是错误的。如果 CPCU 在 运行 秒时确实未定义,并且它传入 {},则此行:

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

会报错,因为它无法访问未定义的Menu属性的mobile属性。因此,虽然开发人员使用一种模式将代码的不同区域分开,但该部分实际上依赖于另一部分(定义 Menu 属性)之前已经 运行,这使得整个 CPCU || {} 没有实际意义。