63 lines
2.0 KiB
JavaScript
63 lines
2.0 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const jpescape = require('./jptr.js').jpescape;
|
||
|
|
||
|
function defaultState() {
|
||
|
return {
|
||
|
path: '#',
|
||
|
depth: 0,
|
||
|
pkey: '',
|
||
|
parent: {},
|
||
|
payload: {},
|
||
|
seen: new WeakMap(),
|
||
|
identity: false,
|
||
|
identityDetection: false
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* recurses through the properties of an object, given an optional starting state
|
||
|
* anything you pass in state.payload is passed to the callback each time
|
||
|
* @param object the object to recurse through
|
||
|
* @param state optional starting state, can be set to null or {}
|
||
|
* @param callback the function which receives object,key,state on each property
|
||
|
*/
|
||
|
function recurse(object, state, callback) {
|
||
|
if (!state) state = {depth:0};
|
||
|
if (!state.depth) {
|
||
|
state = Object.assign({},defaultState(),state);
|
||
|
}
|
||
|
if (typeof object !== 'object') return;
|
||
|
let oPath = state.path;
|
||
|
for (let key in object) {
|
||
|
state.key = key;
|
||
|
state.path = state.path + '/' + encodeURIComponent(jpescape(key));
|
||
|
state.identityPath = state.seen.get(object[key]);
|
||
|
state.identity = (typeof state.identityPath !== 'undefined');
|
||
|
if (object.hasOwnProperty(key)) {
|
||
|
callback(object, key, state);
|
||
|
}
|
||
|
if ((typeof object[key] === 'object') && (!state.identity)) {
|
||
|
if (state.identityDetection && !Array.isArray(object[key]) && object[key] !== null) {
|
||
|
state.seen.set(object[key],state.path);
|
||
|
}
|
||
|
let newState = {};
|
||
|
newState.parent = object;
|
||
|
newState.path = state.path;
|
||
|
newState.depth = state.depth ? state.depth+1 : 1;
|
||
|
newState.pkey = key;
|
||
|
newState.payload = state.payload;
|
||
|
newState.seen = state.seen;
|
||
|
newState.identity = false;
|
||
|
newState.identityDetection = state.identityDetection;
|
||
|
recurse(object[key], newState, callback);
|
||
|
}
|
||
|
state.path = oPath;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
recurse : recurse
|
||
|
};
|
||
|
|