jQuery.extend extends a target object with properties from other objects and it’s widely used in every piece of jQuery code.

Really it’s very useful and simple to undestand and use for flat properties.

jQuery.extend( 
  { a:1, b:'2' }, 
  { a:'1', c:3 } 
) == 
  { a:'1', b:'2', c:3 }

On the contrary, if the involved objects have object properties, jQuery.extend is less intuitive and less useful too.

jQuery.extend( 
  { a:{ x:1 }, b:'2' }, 
  { a:{ y:'1' }, c:3 } 
) == 
  { a:{ y:'1' }, b:'2', c:3 }

Luckily, an undocumented feature (deep) makes jQuery.extend recurr object properties.

jQuery.extend( true, 
  { a:{ x:1 }, b:'2' }, 
  { a:{ y:'1' }, c:3 } 
) == 
  { a:{ x:1, y:'1' }, b:'2', c:3 }

Unluckily, deep only works for the first level. (not really a ‘bug’)

jQuery.extend( true, 
  { a:{ x:1, z:{ m: '' } }, b:'2' }, 
  { a:{ y:'1', z:{ n: 0 } }, c:3 } 
) == 
  { a:{ x:1, y:'1', z:{ n:0 } }, b:'2', c:3 }

If you need deep recursion use jQuery.extend_deep instead.

jQuery.extend_deep( true, 
  { a:{ x:1, z:{ m: '' } }, b:'2' }, 
  { a:{ y:'1', z:{ n: 0 } }, c:3 } 
) == 
  { a:{ x:1, y:'1', z:{ m:'', n:0 } }, b:'2', c:3 }

Here is the jQuery.extend_deep plugin:

/**
 * Implement deep object extension 
 * by replacing the line 599 of jQuery-1.2.3.js
 * (commented out in this function)
 */
jQuery.extend_deep = function() {
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	if ( target.constructor == Boolean ) {
		deep = target;
		target = arguments[1] || {};
		i = 2;
	}

	if ( typeof target != "object" && typeof target != "function" )
		target = {};

	if ( length == 1 ) {
		target = this;
		i = 0;
	}

	for ( ; i < length; i++ )
		if ( (options = arguments[ i ]) != null )
			for ( var name in options ) {
				if ( target === options[ name ] )
					continue;

				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
//					target[ name ] = jQuery.extend( target[ name ], options[ name ] );
					target[ name ] = jQuery.extend_deep( true, target[ name ], options[ name ] );

				else if ( options[ name ] != undefined )
					target[ name ] = options[ name ];

			}

	return target;
};