Hacker News new | ask | show | jobs
by HugoDaniel 3263 days ago
I would really love to see an object map function. I know it is easy to implement, but since they seem to be gaining ranks through syntax sugar, why not just have a obj.map( (prop, value) => ... ) ? :)
5 comments

Is Object.entries(obj).map((prop, value) => ...) close enough? Object.entries is newly standard in ES8.
Not really object map. Does not return a new object ;)
Ah, well this would return a new object:

    Object.entries(obj).map((prop, value) => ...).reduce((newOdj, [prop, value]) => newObj[prop] = value);
I see your point about verbosity :)
Shouldn't it be ".map(([prop, value]) => ...)" ?

I like to write it this way, using as much syntax sugar as possible:

const mapObject = fn => obj => Object.assign( ...Object.entries(obj).map( ([key, value]) => ({ [key]: fn(value) }) ) );

>using as much syntax sugar as possible

It's not possible to say this on the internet without being rude so, apologies, but, why code like that? It genuinely was a struggle to parse (in my brain) your oneliner of code there. If I found this in our code base it would be a huge waste of time and energy.

No offense taken.

I said I like to write it this way, not that I always do it.

> why code like that

It's a fun exercise.

> it would be a huge waste of time and energy

I don't fully agree on this: from the name and signature it's pretty clear what the function does, so you don't need to waste time "parsing" the details. And with unit tests it is also very low-risk.

But that's speculative, in a real project I'd just use lodash.

In production code, if I ever have clever one-liners, they're usually offset with just as many additional lines of comments to explain what it's doing and why it works. Plus, this function is generic and would probably be extracted into a utility module, anyway.

To your point, though, this one is pretty esoteric.

the trend of style over readability. google recommends avoiding list comprehensions in python yet 99% of stackoverflow python questions have some convoluted list comprehension answer
I really like that... I've tended to use Object.assign in a reducer, but this works too, and is a little cleaner imho
Yep, it should be. Thanks for catching it.
Your linter will also complain about modifying newObj within the reducer.
Which a problem with using linters, not with programming.
Spread syntax should cover linter issues

  Object.entries(obj).map(...).reduce((acc, [prop, value]) => ({...acc, prop:value}))
isn't that hideously inefficient? you're making a new object each iteration.
In those cases, I usually use

    Object.assign(acc, { [prop]:value })
While not sure if `[prop]` is better or worse than not creating a new interstitial object.
Which linter rule is that?
The one that doesn't like modifying function arguments?
Even in es5 you can do Object.keys().reduce().
Object.assign({},obj)
Perhaps use the new ‘Map’ object in ES6 instead?
I believe that one of the main reasons not to do this is that adding anything to `Object.prototype` means that now everything inherits that new method.

So you have weird things like `'foo'.map()`, `( 42 ).map()`, `new WeakMap().map()`, `false.map()`, etc.

Those all sort of make sense to me.

'foo' is a string and can be iterated over.

42 is a number that can be provided to a function. Not sure about this one tbh. Could be useful for passing a number to a function if-and-only-if the number is valid (not NAN)

WeakMap(), I don't know what it is but I assume it's a map that can be iterated over.

mapping 'false' would fit well the Maybe monad.

But what are the own properties of a number? There's nothing to iterate, and therefore nothing to map.

WeakMap is a new-ish type whose keys are objects. The references to those objects are weakly held, which means that an object `x` whose only reference is a WeakMap key will still be eligible for garbage collection. They are non-iterable for exactly that reason.

Also: how do you iterate over `false` or a function? What about user-created classes?

There are so many cases where the behavior would either be nonsensical or at least unintuitive that (in my personal and completely subjective opinion) they outweigh the slight convenience of being able to "map" a plain old JavaScript object.

No answer for WeakMap, and like I said, not sure about integers, but if you take a look at Haskell monads, you'll see that surprising things like Maybe (booleans, essentially, or rather container classes that either contain something or don't) can be iterated over. It's a very useful concept that abstracts somewhat the idea of "iterable", to "do something with all the things", where in the case of Maybe, all the things is either one thing or nothing.

Granted, in JavaScript maybe this wouldn't make sense.

Actually WeakMap() could not be iterated over as its keys are not enumerable by design - you can't "know" at any given time what the list of keys actually contains.
Fair enough.
Adding a `map` method to every single object is not a backwards-compatible change. That's why those new methods are under the `Object` global.
Until then, lodash.mapValues is your friend :P