JavaScript-Composite Pattern - 书目录

JavaScript-Composite Pattern

The Composite Pattern

The Composite Pattern describes a group of objects that can be treated in the same way a single instance of an object may be.

This allows us to treat both individual objects and compositions in a uniform manner, meaning that the same behavior will be applied regardless of whether we’re working with one item or a thousand.

In jQuery, when we’re applying methods to an element or collection of elements, we can treat both sets in a uniform manner as both selections return a jQuery object.

This is demonstrated by the code sample using the jQuery selector below. Here it’s possible to add an active class to both selections for a single element (e.g an element with a unique ID) or a group of elements with the same tag name or class, without additional effort:

1
2
3
4
5
6
7
8
// Single elements
$( “#singleItem” ).addClass( “active” );
$( “#container” ).addClass( “active” );
// Collections of elements
$( “div” ).addClass( “active” );
$( “.item” ).addClass( “active” );
$( “input” ).addClass( “active” );

 

The jQuery addClass() implementation could either directly use native for loops (or jQuery’s jQuery.each()/jQuery.fn.each()) to iterate through a collection in order to apply the method to both single items or groups. Looking through the source we can see this is indeed the case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  addClass: function( value ) {
  var classNames, i, l, elem,
    setClass, c, cl;
  if ( jQuery.isFunction( value ) ) {
    return this.each(function( j ) {
      jQuery( this ).addClass( value.call(this, j, this.className) );
    });
  }
  if ( value && typeof value === “string” ) {
    classNames = value.split( rspace );
    for ( i = 0, l = this.length; i < l; i++ ) {
      elem = this[ i ];
      if ( elem.nodeType === 1 ) {
        if ( !elem.className && classNames.length === 1 ) {
          elem.className = value;
        } else {
          setClass = ” ” + elem.className + ” “;
          for ( c = 0, cl = classNames.length; c < cl; c++ ) {
            if ( !~setClass.indexOf( ” ” + classNames[ c ] + ” ” ) ) {
              setClass += classNames[ c ] + ” “;
            }
          }
          elem.className = jQuery.trim( setClass );
        }
      }
    }
  }
  return this;
}