Augmented Configuration Pattern

When a JavaScript object can be configured in a variety of ways, it is best-practice to include a configuration object in the constructor, where all configuration values are optional. This way, the developer can configure an object when it is instantiated, without having to provide parameters that are common to most instances of an object.

Example 1: Using A Configuration Object

 var YL = YAHOO.lang;
 var testFunction = function(conf) {
	var cfg = YL.isObject(conf) ? conf : {};
	
	// default configuration
	if (! YL.isArray(cfg.rows)) {cfg.rows = [];}
	if (! YL.isNumber(cfg.size)) {cfg.size = 10;}
	// etc…
	
	this._cfg = cfg; // so configuration is available to prototype attached functions
 }
 
 testFunction.prototype = {
	_cfg: null,
	doSomething: function() {
		for (var i = 0, j = this._cfg.size; i < j; i += 1) {
			// …
		}
	},
	// …
 }

Sometimes, however, a configuration is defined when the object is instantiated, but on occasion certain configuration options need to be temporary overwritten when a member function executes. From Example 1, lets assume that occasionally the size parameter needs to be changed. To achieve this is the most generic way, the doSomething function must now except a contextual configuration object as its last parameter.

Example 2: Augmented Configuration

testFunction.prototype = {
	_cfg: null,
	doSomething: function(conf) {
		var cfg = conf;
			
		if (YL.isObject(cfg)) {
			YL.augmentObject(cfg, _cfg, false);
		}
		else {
			cfg = _cfg;
		}
		
		for (var i = 0, j = cfg.size; i < j; i += 1) {
			// …
		}
	},
	// …
 }

The new configuration object passed into the function will be used for that functions context only. If the configuration object is not provided, then the objects default configuration object will be used. However, when a new configuration object is used, it is then augmented by the default configuration, adding any values to the context configuration that do not already exist. Since the third parameter of augmentObject is false (falsy values are fine as well) no values on the context configuration object are overridden, thereby preserving any configuration modifications, while sharing all other configuration options.

In a simple example, such as Example 2, one could pass the new size as an optional parameter into the doSomething method, instead of an object. However, if there were 2 or more overridable configuration options, then passing optional parameters would become cumbersome and the Augmented Configuration pattern becomes much more useful.