UIZE JavaScript Framework

2012 NEWS 2012-01-22 - New Uize.mergeInto Method

The new Uize.mergeInto static method, implemented in the Uize base module, merges the contents of one or more source objects into the specified target object, and returns the target object as the result.

DIFFERENT USAGES

Merge the Contents of a Source Object Into a Target Object

targetOBJ = Uize.mergeInto (targetOBJ,sourceOBJ);

Merge Multiple Source Objects Into a Target Object

targetOBJ = Uize.mergeInto (targetOBJ,source1OBJ,source2OBJ,...,sourceNOBJ);

1. Merge the Contents of a Source Object Into a Target Object

In the most simple use case, the Uize.mergeInto method can be used to merge the contents of a single source object into a target object.

SYNTAX

targetOBJ = Uize.mergeInto (targetOBJ,sourceOBJ);

The contents of the source object is merged into the target object according to the Uize.mergeInto method's merging rules.

EXAMPLE

var
  targetObject = {
    foo:'bar',
    anArray:[0,1,2],
    junk:{
      hey:'there',
      moreJunk:{
        simple:'simon'
      }
    }
  },
  sourceObject = {
    foo:'BAR',
    anArray:['a','b','c'],
    junk:{
      boo:'yah',
      moreJunk:{
        peter:'pan',
        evenMoreJunk:{
          silly:'sausage'
        }
      }
    }
  }
;
Uize.mergeInto (targetObject,sourceObject);

RESULT

{
  foo:'BAR',
  anArray:['a','b','c'],
  junk:{
    hey:'there',
    moreJunk:{
      simple:'simon',
      peter:'pan',
      evenMoreJunk:{
        silly:'sausage'
      }
    },
    boo:'yah'
  }
}

2. Merge Multiple Source Objects Into a Target Object

As a convenience, the contents of multiple source objects can be merged into a target object by specifying an arbitrary number of source objects after the targetOBJ first parameter.

SYNTAX

targetOBJ = Uize.mergeInto (targetOBJ,source1OBJ,source2OBJ,...,sourceNOBJ);

When multiple source objects are specified, the contents of the source objects are merged into the target object in the order in which they are specified (ie. left to right in the arguments list). The contents of source objects are merged into the target object according to the Uize.mergeInto method's merging rules.

EXAMPLE

var
  targetObject = {
    foo:'bar',
    anArray:[0,1,2],
    junk:{
      hey:'there',
      moreJunk:{
        simple:'simon'
      }
    }
  },
  sourceObject1 = {
    foo:'BAR',
    anArray:['a','b','c'],
    junk:{
      boo:'yah',
      moreJunk:{
        peter:'pan',
        evenMoreJunk:{
          silly:'sausage'
        }
      }
    }
  },
  sourceObject2 = {
    hello:'world',
    anArray:['A','B','C'],
    junk:{
      yo:'wassup'
    }
  },
  sourceObject3 = {
    foo:'BAR!!!',
    junk:{
      moreJunk:{
        evenMoreJunk:{
          bite:'me'
        }
      }
    }
  }
;
Uize.mergeInto (targetObject,sourceObject1,sourceObject2,sourceObject3);

RESULT

{
  foo:'BAR!!!',
  anArray:['A','B','C'],
  hello:'world',
  junk:{
    hey:'there',
    moreJunk:{
      simple:'simon',
      peter:'pan',
      evenMoreJunk:{
        silly:'sausage',
        bite:'me'
      },
    },
    boo:'yah',
    yo:'wassup'
  }
}

3. Merging Rules

The Uize.mergeInto method merges the contents of source objects into a target object according to the following set of rules...

3.1. Merging is Recursive

The contents of a source object is merged into the contents of the target object recursively.

EXAMPLE

var result = Uize.mergeInto (
  {foo:{bar:{hello:'world'}}},
  {foo:{bar:{boo:'yah'}}}
);

RESULT

{foo:{bar:{hello:'world',boo:'yah'}}}

3.2. Only Plain Objects Are Recursed

Only the contents of plain objects are recursed, and non-plain objects are copied by reference.

EXAMPLE

function CustomObject (value) {this.value = value}

var
  customObject1 = new CustomObject (5),
  customObject2 = new CustomObject (42)
;
customObject1.foo = 'bar';
customObject2.hello = 'world';

var result = Uize.mergeInto (
  {prop:customObject1},
  {prop:customObject2}
);

In the above example, a constructor is created for a custom object called CustomObject. Then, we create two different instances of this object. To each instance, we add extra properties.

Now, when we use the Uize.mergeInto method to merge a source object into a target object, where the value of a prop property in the source object is customObject2 and the value of that same property in the target object is customObject1, the value of the prop property in the target object is simply overwritten with a reference to the customObject2 value contained in the source object - the contents of customObject2 are not merged into customObject1.

In other words, the merge process does not recurse into the properties of the CustomObject instances (or any non-plain objects, for that matter). The Uize.mergeInto method considers custom objects to be values rather than nodes of the object tree.

3.3. Missing Nodes Copied By Reference

When the target object being recursed is missing a node, at any level of its structure, that is present in the source object, then the node from the source object is copied by reference - it is not cloned.

EXAMPLE

var
  targetObject = {foo:'bar'},
  sourceObject = {aMissingNode:{hello:'world'}}
;
Uize.mergeInto (targetObject,sourceObject);

alert (targetObject.aMissingNode === sourceObject.aMissingNode);  // alerts "true"

In the above example, the sourceObject object contains the property aMissingNode, whose value is a plain object and represent a node in the object structure that is not present in the targetObject object. When the source object is merged into the target object, this missing node is copied by reference - it is not cloned into the target object. Therefore, the expression target.aMissingNode is identical in a strict equality to sourceObject.aMissingNode.

This same rule applies if the target object contains the property that is contained in the source object, but the value of the property in the target object is not a plain object.

EXAMPLE

var
  targetObject = {someProperty:'foo'},
  sourceObject = {someProperty:{hello:'world'}}
;
Uize.mergeInto (targetObject,sourceObject);

alert (targetObject.someProperty === sourceObject.someProperty);  // alerts "true"

In the above example, the sourceObject object contains the property someProperty, which is also present in the targetObject object. However, the value of this property in the target object is a string, so this value is overwritten with a reference to the object value of the property obtained from the source object. Therefore, the expression target.someProperty is identical in a strict equality to sourceObject.someProperty.

3.4. Null or Undefined Source Objects Ignored

As with the related Uize.copyInto method, specifying the values null or undefined for source object parameters results in those parameters simply being ignored - they contain nothing to merge into the target object.

EXAMPLE

Uize.mergeInto (
  {foo:'bar',junk:{hello:'world'}},
  null,
  {foo:'BAR'},
  undefined,
  {junk:{simple:'simon'}}
);

RESULT

{foo:'BAR',junk:{hello:'world',simple:'simon'}}