UNPKG

@mmckelvy/map-object

Version:

Map over an object calling a function on each key / value pair.

58 lines (50 loc) 1.53 kB
function isObject(item) { return ( typeof item === 'object' && item !== null && !(item instanceof RegExp) && !(item instanceof Error) && !(item instanceof Date) && !Array.isArray(item) ); } /** * map over an object calling a function on each key / val pair. * * @param {object} obj - The source object. * @param {function} fn - A function to call on each key / val pair. * function signature is as follows: * @param {string} key * @param {any} value * @param {object} source - The source object. * @return [] - An array with [targetKey, targetValue] elements. * * @param {object} options - Includes the following keys: * @param {boolean} options.recursive - map over nested objects / arrays. * * @return {object} - The mapped object. */ module.exports = function mapObject(obj, fn, { recursive = false } = {}) { if (!isObject(obj)) { throw new TypeError(`Expected an object, got ${typeof obj}`); } return Object.keys(obj).reduce((acc, key) => { const [ newKey, newValue ] = fn(key, obj[key], obj); // handle arrays if (Array.isArray(obj[key])) { acc[newKey] = obj[key].map((el) => { if (isObject(el) && recursive) { return mapObject(el, fn, {recursive: true}); } return el; }); // handle nested objects } else if (isObject(obj[key]) && recursive) { acc[newKey] = mapObject(obj[key], fn, {recursive: true}); // base case } else { acc[newKey] = newValue; } return acc; }, {}); };