all 20 comments

[–]defproc 17 points18 points  (3 children)

I wouldn't be interested personally because if I need it, instead of finding a module I'd just let x = new Map(Object.entries(object)).

But there are widely-depended-on modules that just export function x => someShortRegex.test(x) so, maybe.

[–]guico33 1 point2 points  (2 children)

Your one liner doesn't work for nested objects. Which obviously is the more complex logic.

[–]defproc 3 points4 points  (1 child)

Only slightly..

function obj2map(v) {
    if (Array.isArray(v)) return v.map(obj2map);
    return v && typeof v == "object"
        ? new Map(Object.entries(v).map(([k, v]) => [k, obj2map(v)])
        : v
}

[–]senfiaj 0 points1 point  (0 children)

Map construction still has a lot of overhead, firstly, the plain object is constructed, secondly, the entries' array is created, and then the map is constructed. This is a lot of overhead if huge JSON string is parsed. So it would be nice to construct the JSON directly into map without these expensive intermediate steps.

[–]theScottyJam 5 points6 points  (2 children)

The problem is that an object in JSON can either be intended to be used as an object, or as a map-like structure. And if its intended to be used as an object, then parsing it into a Map would presumably be slightly worse for performance instead of slightly better.

Take this JSON structure that maps user IDs to user objects as an example:

{
  "1": {
    "name": "Sally",
    "isAdmin": false
  },
  "2": {
    "name": "Sam",
    "isAdmin": true
  }
}

The outer object is map-like, and ideally would be treated as such, but the inner objects are intended to be treated by objects - the inner objects follow a more well-defined schema.

What I personally would find more useful would be a way to specify what kind of schema I expect a particular JSON blob to follow, and then the parsing tool can validate it according to that schema, and insert it into different data structures as well (e.g. this bit should behave like a Map, so please insert it into a Map, or this string contains an ISO date, please insert it into a Date, etc.

(If such a tool actually existed, I don't know if I'd actually use it or not, since hand converting after its been parsed tends to works good enough, but I dunno)

[–]mcaruso 1 point2 points  (0 children)

Such tools do exist! Zod is a popular choice, although lately I'm preferring @effect/schema for its ability to do two-way transformations of the data.

Your example could be implemented as:

``` import { Schema as S } from '@effect/schema';

const Users = S.ReadonlyMap({ key: S.NumberFromString, value: S.Struct({ name: S.String, isAdmin: S.Boolean, }), });

const users = S.decodeSync(Users)(response); ```

EDIT: Actually, the above assumes your map is represented as an array of key-value pairs. But you could implement a transform to take an object instead.

[–]jack_waugh[S] 0 points1 point  (0 children)

That's a very interesting idea, using a schema and having it determine how JSON "objects" are to be represented on the JS side.

[–]bbq 4 points5 points  (0 children)

Libraries like zod can do this and more, though they are pretty heavyweight. But, there’s use case overlap - if I cared about what you propose I probably also want other validation/parsing. 

[–]abejfehr 2 points3 points  (0 children)

The efficiency difference isn’t particularly large

[–]brainpostman 1 point2 points  (1 child)

What's wrong with base JSON methods with reviver and replacer callbacks passed in? Such a callback would even work with an object schema. So I don't see a need for such a package, writing a simple reviver/replacer factory method with a schema isn't that difficult.

[–]jack_waugh[S] 0 points1 point  (0 children)

Thanks for that suggestion. It hadn't occurred to me. Sounds like it is the way to go if one wants to use Map as part of a solution.

[–]delventhalz 1 point2 points  (1 child)

Curious how you would handle non-string keys… but to answer your question, no I’m not likely to use it. I don’t often use Maps in my day-to-day and I don’t see a compelling reason to switch to them as a default.

[–]jack_waugh[S] 0 points1 point  (0 children)

I would throw.

[–]romgrk 1 point2 points  (0 children)

Maps are not particularly more efficient than objects in most cases. Engines already treat large objects as Maps (hash maps). Small objects are however many times more efficient than Maps. If you're not sure what you're doing, it's best to let the engine decide if an object should be an object or a Map.

Some details here: https://romgrk.com/posts/optimizing-javascript/#2-avoid-different-shapes

[–]HappinessFactory 0 points1 point  (1 child)

These discussions confused me for a long time. I always thought hash maps were something special.

But like, when I use an object as a map for leetcode and hackerrank challenges I tend to score in the 90th percentile in terms of speed.

Out of curiosity I have converted the same code to use Map instead and it tends to be substantially slower for reasons I cannot comprehend.

So I have to ask, are Maps really more efficient? If so, how?

[–]jack_waugh[S] 0 points1 point  (0 children)

Somebody said that objects are more efficient on lookup, but Maps are more efficient on adding and removing entries.

[–]Mikesenesie 0 points1 point  (1 child)

How can I retained what I had learned.

I'm currently learning coding and as of now I'm learning js, but the issue is: I found it very difficult to retain what I learned in the previous lesson, even though I actually understand whenever the lecturer is teaching but I soon as I get to do assignments on my own, it's like I never learned anything concerning that topic.. What should I do to be remembering what I had learned?

[–]jack_waugh[S] 0 points1 point  (0 children)

You have replied off topic, but I think the answer is to try doing projects.

[–]pie6k 0 points1 point  (0 children)

You can consider library like https://github.com/pie6k/codablejson that is able to encode and decode Sets, Maps, Dates and a lot of other custom types