代码组织的第一步是将应用程序分离成不同的代码块;有时,哪怕只做到这一点也是很有意义的。

对象原语可能是最简单的关联代码封装方式了。它不会为属性或方法提供任何隐私保护,但它对于从你的代码中消除匿名函数,集中配置选项,简化重用和重构都很有帮助。


上面的对象原语简单地将一个对象分配给了一个变量。该对象具有一个属性和几个方法。所有的属性和方法都是公有的,因此你应用程序的任何部分都可以访问对象的属性、调用对象的方法。尽管有一个init方法,但在对象实例化之前调用它却没有任何必要。

我们怎样将这种模式应用到jQuery代码中?让我们通过编写传统jQuery风格的代码来说明吧:

//点击一个列表项加载一些内容
//引用列表项的ID并隐藏兄弟列表项的内容
$(document).ready(function() {
  $('#myFeature li')
    .append('<div/>')
    .click(function() {
      var $this = $(this);
      var $div = $this.find('div');
      $div.load('foo.php?item=' +
        $this.attr('id'), 
        function() {
          $div.show();
          $this.siblings()
            .find('div').hide();
        }
      );
    });
});

如果它出现在我们的应用程序范围内,抛弃它可能会更好。换句话说,如果它是一个大型应用程序的一部分,我们最好将这个功能从孤立的功能中分离出来。我们可能想把代码中的URL移到一个配置区域。最后,我们可能想摆脱链式代码的束缚让以后修改功能块更简单一点。


你会关心的第一件事就是这种方式比原来的代码明显要长得多——此外,如果它在我们应用程序的范围内,对象原语的使用则有点泛滥了。假设它不在我们程序的范围内,我们便发现了这样几个事实: The first thing you'll notice is that this approach is obviously far longer than the original — again, if this were the extent of our application, using an object literal would likely be overkill. Assuming it's not the extent of our application, though, we've gained several things:

  • 我们已经将功能特性分解成了短小的方法。如果以后我们需要改变显示内容,在哪里更改将一目了然。

  • 我们已经消除了匿名函数的使用。

  • 我们已经将配置选项移出了代码本身,并将这些配置选项放到了核心位置。

  • 我们已经摆脱了链式代码的束缚,使代码易于重构,重新合成,重新组织。

作为不一般的特性,对象原语是对在$(document).ready()块中在编写冗长代码的明显改进,它迫使我们考虑应用程序的功能块。无论如何,和在$(document).ready()块中简单定义大量函数相比,它们也好不到哪里去。

组件模式突破了对象原语的一些局限性,如有必要可以对外暴露出公有API,为变量和函数提供隐私保护。


在上面的例子里,我们自动执行了一个返回对象的匿名函数。在该函数内部,我们定义了一些变量,因为这些变量是定义在函数内部的,我们无法在函数之外去访问它们,除非我们把它放到返回的对象中。这意味着函数外部的代码无法访问privateThing变量或changePrivateThing函数。不管怎样,sayPrivateThing却可以访问privateThingchangePrivateThing,因为它们和sayPrivateThing处于相同的作用域。

这种模式之所以十分强大,是因为当需要暴露由返回对象的属性和方法构成的受限API时,你可以隐藏这些变量名,形成私有的变量和函数。

下面是上一个例子的修正版本,它向我们展示了仅仅暴露该组件一个公有方法showItemByIndex()时,通过组件模式创建相同的特性。