.explore() - DarthJDG/Mangler.js GitHub Wiki
Traverses all nested objects and arrays in the items array, calling a function for each key/value pair.
.explore(callback[, state])| Parameter | Type | Default | Description |
|---|---|---|---|
| callback | Function | Function to call for every key/value pair. Parameters: function(key, value, state). |
|
| state | Object | {} |
Initial value of the state object passed down the hierarchy. |
Returns a reference to the mangler object itself for chaining.
| Property | Type | Description |
|---|---|---|
| $path | String | Describes the current value's path from the root of the iteration. |
| $parent | Instance | Points to the object which has the current value at the given key. |
| $parentPath | String | The path of the parent from the root of the iteration. |
| $prop | String | The last known property name of the value. If the current value is an array element, it looks further up the path. If the it's an object property, state.$prop is the same as key. Could be an empty string if there's no object property in the path. |
The callback function is called for each key/value pair in all iterable objects in the .items[ ] array, traversing items recursively. For arrays, the array index is passed as the key and the item is passed as the value parameter. For objects, the callback function is called for each property with the property name in key and the property value in value.
If value is an iterable object, returning false from the callback function will prevent .explore() to go further and traverse value itself.
Apart from object literals and arrays, other typed objects may be made iterable and could be traversed. See Mangler.registerType() for details.
The $path property of the state parameter is the full reference of the current object relative to the mangler object's .items array.
If we create a mangler object from the following object:
{ children: [{ name: 'Child' }] }then the callback parameters for the name property would be:
callback('name', 'Child', {
$path: '[0].children[0].name',
$parent: { name: 'Child' },
$parentPath: '[0].children[0]',
$prop: 'name'
})The initial value of the state callback parameter can be set by passing an object to the .explore() method. It will be passed down the hierarchy, but changes will only be visible from the same level down. When .explore() goes into a child object or array, it creates a shallow copy of the state object's properties to pass on. You can use any properties apart from the built-in $-prefixed ones, which will be overwritten.
data = {
object1: {},
object2: {},
array1: [{}, {}, {}],
array2: [{}, {}, {}]
};
// Use .explore() to add object properties using a counter in the state object
Mangler(data).explore(function(key, value, state) {
if(Mangler.isObject(value)) {
state.counter += 1;
value.counter = state.counter;
}
}, { counter: 0 });
/*
data = {
counter: 1,
object1: { counter: 2 },
object2: { counter: 3 },
array1: [{ counter: 4 }, { counter: 5 }, { counter: 6 }],
array2: [{ counter: 4 }, { counter: 5 }, { counter: 6 }]
}
*/As the method traverses array1 and array2, the state object is reset to its previous value, before it started processing the arrays.
The above example is only to explain the state object. Please note that there is no guarantee that object properties will be traversed in any particular order.
The .explore() method is useful for processing tree structures. The state object can be used to collect data from the parents and pass it down to the child nodes. In the following example, we add a depth property to all objects by increasing a counter in the state object when we start processing an array:
data = {
name: 'Root',
children: [
{
name: 'Child 1',
children: [
{
name: 'Sub-child 1'
},
{
name: 'Sub-child 2'
}
]
},
{
name: 'Child 2'
}
]
};
Mangler(data).explore(function(k, v, state) {
if(Mangler.isArray(v)) {
state.depth += 1;
} else if(Mangler.isObject(v)) {
v.depth = state.depth;
}
}, { depth: 0 });
/*
data = {
depth: 0,
name: 'Root',
children: [
{
depth: 1,
name: 'Child 1',
children: [
{
depth: 2,
name: 'Sub-child 1'
},
{
depth: 2,
name: 'Sub-child 2'
}
]
},
{
depth: 1,
name: 'Child 2'
}
]
}
*/