mapValues and mapKeys are Array.prototype.map for objects. mapValues transforms every value while keeping the keys; mapKeys transforms every key while keeping the values. Both return a new object with the same number of entries, just reshaped.
Implement both. Each takes (obj, iteratee), where iteratee(value, key) produces the new value (for mapValues) or the new key (for mapKeys). Return a new object; don't mutate the input.
function mapValues(obj, iteratee) {} // same keys, iteratee(value, key) as each value
function mapKeys(obj, iteratee) {} // same values, iteratee(value, key) as each key
mapValues({ a: 1, b: 2 }, (v) => v * 10); // { a: 10, b: 20 }
mapKeys({ a: 1, b: 2 }, (v, k) => k.toUpperCase()); // { A: 1, B: 2 }
// The iteratee gets both value and key:
mapValues({ a: 1 }, (v, k) => `${k}=${v}`); // { a: 'a=1' }
mapKeys({ a: 1, b: 2 }, (v) => `k${v}`); // { k1: 1, k2: 2 }
mapValues keeps keys; mapKeys keeps values — each changes exactly one axis.(value, key), in that order (value first), matching lodash.mapKeys, the later entry wins.