mf Object Methods Part 2 {mf.object}

This is a series of posts that explains some of the fundamental rules for developing complex JavaScript applications and the mf framework.

In my previous post on the mf object methods I discussed several methods that act against a single object. In this next series of object methods I will begin demonstrating some of the mf object methods that deal with arrays of objects. When we look at applications within the business sphere we in most cases have to deal with large amounts of data that is displayed in grids and other standard user interface implementations. When dealing with this type of data you need to envision, in regards to a grid, what types of behaviour and functionality you need to provide to the consumer. There are some obvious features like sorting and search plus filter. As such we need to provide these types of methods as part of the object methods. In the future of mf I will be developing a store object which will make significant use of these methods. In this post I will discuss the following methods…

  • mf.object.exec
  • mf.object.normalize
  • mf.object.merge
  • mf.object.sort
  • mf.object.search
  • mf.object.difSearch


mf.object.exec (mixed, function, deep, desctructive)

The object.exex method allows you to enumerate through an array of objects or a single object and place the result of the provided function as the value of the property. The function is passed three arguments as the enumeration of the object is run. The value of the property, property namespace and the root object instance. You can optionally pass the deep boolean which defaults to false if you require deep object enumeration. The final parameter destructive is also optional boolean that defaults to true. When set to false the passed object or object array is first cloned and then returned. For example..

var myObject = [
{z:1,x:'a',b:undefined},
{
    a:{
        aa:1,
        bb:2
    },
    f: 1
}]
mf.object.exec(myObject,function(val){return mf.isNumber(val)?val*10:val},true,false)

The result of the exec method would return an array which has been cloned with the following values:

{z:10,x:'a',b:undefined},
{
    a:{
        aa:10,
        bb:20
    },
    f: 10
}]

Since the destructive argument was set to false the original myObject has not been modified.

mf.object.normalize(array, value)

The normalize object method takes and array object mixed objects and ensures that each object all have the same properties. For example given the following call:

var myObject = [
{z:1, x:'a', b:'z'},
{
    z:2,
    a:{aa:1,bb:2},
    f: 1
}]
mf.object.normalize(myObject);
The result would be:
[
 {
    z:1, 
    x:'a', 
    b:'z',
    a:{aa:null,bb:null},
    f:null
 },
 {
    z:2,
    x:null,
    a:{aa:1,bb:2},
    b:null,
    f: 1
 }
]

As can bee seen both objects now share all of the same properties. The optional second parameter value is the default value to assign to properties that are created in each object in order to normalize. By default the value argument is Null.

When we dealing with large datasets being pulled via AJAX requests one of our goals is to reduce the size of this request as much as possible.  When dealing with these large sets most often all of the object definitions match on properties in the JSON requests even specific fields are null. On these large requests returning that a field is Null is wasteful on the request pipe. By using the mf.object.normalize method you can retrieve your data optimized for transport then use normalize it within the client. It should be taken into account however that running the normalize method against very large datasets is not recommended as it takes several passes on the data in order to normalize. Like any implementation a balanced approach needs to be taken by testing the performance versus request time.

mf.object.merge(array, function, deep)

Merges an array of objects into a single object allowing the ability to do things such as summed sets. For example:

var data=[
{a:1,b:6},
{a:4,c:{y:2}},
{a:2,b:1,c:{x:1,y:1}}
];
mf.object.merge(data,function(prop,obj,ns,depth,mergeObjVal,mergeObj){obj[prop]+=mergeObjVal},true)

The method would then return

{
  a:7,
  b:7,
  c:{
     x:3,
     y:3
   }
}

The merge method initially clones and normalizes the passed array of data so it is not destructive. The deep parameter is optional and is true by default. The function argument is passed several parameters to allow for direct changes to the both the current object and the resulting object. The function is passed the present object property along with the object root the current namespace as a string and the namespace depth.  The function is also passed the current value for the matching namespace in the merge object and the root of the merge object as well. The result of this function is always the merge object itself.

mf.object.sort(array, key, ascending)

Sorts an array of objects based on the provided key and its subsequent value. This method does NOT do a deep enumeration of each object so the key/property as string must exist at the root of each object. The boolean ascending is true by default to sort in descending order pass false. For example:

var data=[
{a:1,b:6},
{a:4,b:3,c:{y:2}},
{a:2,b:1,c:{x:1,y:1}}
];
mf.object.sort(data,'a')

The passed data will now be sorted ascending by the value contained in the root a property of the objects. This method does NOT do any data normalization to ensure that the provided property key exists in each object.

mf.object.search(propertySet, array)

Search an array of objects and returns an array of those objects matching the propertySet. This method does not support deep object enumeration, use intersect for deep enumeration. The property set is by definition a simple object that allows for matching of property values. For example:

var data=[
{a:1,b:6},
{a:4,b:3,c:{y:2}},
{a:2,b:1,c:{x:1,y:1}}
];
mf.object.search({a:4},data)

This would return an array containing one object from data whose a property was equal to 4. The property set parameter can also contain functions that must return true or false. Consider the following scenario:

var data = [
 {title:'Welcome to my framework'},
 {title:'Using Object Methods',b:2},
 {title:'Object.intersect Method in Detail',b:1}
];
mf.object.search({b:2,title:function(val){return val.match('Object')}},data)

In this case we are checking the title to see if the value contains the word object and also is its b property is equal to 2. The result would be the second object from the array. This is a not a descructive method and the passed objects are NOT cloned into the resulting array so all pointers would still remain intact.

mf.object.difSearch(propertySet,array)

The difSearch method is identical in nature to search but returns an array of objects that do not meet the search requirements. As an example:

var data = [
 {title:'Welcome to my framework'},
 {title:'Using Object Methods',b:2},
 {title:'Object.intersect Method in Detail',b:1}
];
mf.object.difSearch({b:2,title:function(val){return val.match('Object')}},data)

This call would result in only the first array object being returned as both the 2nd and 3rd objects fail on one or more of the tests.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s