← Daily Logs
GreatFrontEnd

Implement objectMap

EasyJul 2, 2026objectsiterationthis

The obvious version — loop the keys, call `fn` on each value — passes every test except one: `fn` needs to see the object being mapped as its `this`, not `undefined`. That single failing case is the whole exercise; the mapping logic itself was never the hard part.

The problem

Write `objectMap(obj, fn)` returning a new object with the same keys as `obj`, where each value is the result of calling `fn` on the original value: `objectMap({ foo: 1, bar: 2 }, x => x * 2)` → `{ foo: 2, bar: 4 }`. The input object must not be mutated.

The hidden requirement lives in one test: when `fn` is a regular (non-arrow) function that reads `this.foo`, it must see the original object as `this` — `objectMap({ bar: 3, foo: 2 }, function (x) { return this.foo * x; })` has to resolve `this.foo` to `2` for every key, not `undefined`.

The approach

The loop itself is unremarkable: `for...in` over `obj`, building a fresh `res` object so the input is never touched — `res[key] = fn(obj[key])` passes every test that doesn't touch `this`.

The one line that needs to change is the call itself. `fn(obj[key])` is a plain function call, and a plain call gives a regular function `this === undefined` in strict mode — it never sees `obj`. Calling it as `fn.call(obj, obj[key])` instead binds `this` to `obj` for that invocation, which is exactly what the failing test needs and costs nothing for callers (like `double`) that ignore `this` entirely.

The solution

js
export default function objectMap(obj, fn) {
  if (!obj) return {};
  const res = {};
  for (const key in obj) {
    // call, not fn(obj[key]) — lets fn see obj as `this`
    res[key] = fn.call(obj, obj[key]);
  }
  return res;
}

Time O(n)Space O(n)

All entries