Hacker News new | past | comments | ask | show | jobs | submit login
New JavaScript Set Methods (developer.mozilla.org)
92 points by soheilpro 4 months ago | hide | past | favorite | 38 comments



I'm very excited this finally shipped everywhere! Prior to this Set wasn't much more than a Map<any, true> since it had no actual Set operations.


Oh, that's a relief. Having "set" objects in JS, without having any of the standard set operations, didn't make a lot of sense.


Blog post author here in case there's any feedback or questions. Thanks for sharing :)


Thanks for the post. One thing, I wanted to test this in chrome and I realized your examples are all based on a larger Playground with a test HTML doc.

Maybe one self-contained example w/ a new function you can copy/paste into the console to play around with would be cool.

I was mostly using it as a test to see if it worked in Chrome so I could start using it.


That's a good idea. I'll have a think about a JS only example, although the reference pages have some, they log results to the console and so I thought some HTML might be interesting to see.

Maybe it's interesting for you: the method pages have compat data at the bottom so you can see what's supported and in which browser release.


It was replaceAll in 2021 and now this! Who knows what we’ll get in 2030. Maybe Array.prototype.last() even.


It should be available as .at(-1)


Thanks!


> It's also typically faster to check if an element is in a set as opposed to in an Array

What optimisations allow that? As sets in javascript maintain insertion order, aren’t lookups O(n) ?


According to the Mozilla docs, O(n) lookups would actually violate the spec [0]. As a sibling comment says, a tree set is one option to satisfy the spec. Another is a linked hash set, which would have O(1) lookups [1].

0: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

1: https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHa...


It is usually implemented by a linked list + hash set (Java call this, drumroll... LinkedHashSet).

Because we are not adding elements in the middle of the list, only the end (we only care about insertion order), `add` is still O(1). `has` searches on the HashSet so it is also O(1). Delete is a bit more complex, you need to keep the list node reference on the set node, and then just splice it from the list. So O(1) as well

Of course this takes a lot more memory, but I think it usually pays off to have consistent ordering for sets, undefined/non-deterministic behavior is a virus and it spreads very quickly


Probably a tree set, with O(log(n)) lookups


It's a pity that you can't implement a function in an object to consider it equal to another object with the same member values.


There is a years-old proposal for deeply-comparable types: https://github.com/tc39/proposal-record-tuple

Maybe we'll see it one day.


I highly doubt this will go anywhere, it is much more likely to get some custom equality in data structures.

For example I would like a Map<array, any> that compare keys by shallow equality, so to behave like multidimensional tables


This'll help with AoC. Just need sensible tuples now and we'll be golden. See you in ten years.


Perhaps it's asking too much but it would be great to see performance comparisons of these new set methods versus naive JS.

Not sure when I'll have a chance to use them but seems pretty comprehensive in covering all the basics.


Agree, a main benefit of using these would be performance gains.


[6,-2,2,-7].sort()

Result : [-2,-7,2,6]

Ladies and Gentlemen, the lingua franca of web programming.


new Int32Array([2,7,-2, -7]).sort()

Result: Int32Array [-7, -2, 2, 7] (4)

The problem is you can put anything in array and JS can't really check that "everything here is a number", so it uses string as a common type because everything can be converted to string.

we need proper typed arrays, like Int8/16/32Array but with any class, not just int. The class itself will then define how to compare instances (python's __gt__ and so on).


Because js sort works on string. for numeric sort try:

`[6,-2,2,-7].sort( (a,b) => a-b)`


It would be cool if an array of numbers was sorted by numeric value by default, instead of the values being sorted alphanumerically, yes, that’s a gotcha.


Someone didn't read the docs.


Huh. I might actually start using sets over just simple objects. Never found a great reason to use them before these methods, other than to show off.


Objects not really safe to use as sets:

    const x = {};
    ‘constructor’ in x // true
    x[‘constructor’] === Object // true
You have to use hasOwnProperty and people don’t remember to do this.

Some properties cannot be deleted, and some cannot be modified:

    delete x.constructor;
    x.constructor === undefined // false
    x.__proto__ = undefined;
    x.__proto__ === undefined // false
Sets also allow you to have sets of other types rather than just strings and symbols.


Yup. I always use Set and Map over objects. They just contain way fewer surprises and the APIs actually work as you would expect. I only use Objects for "struct" like objects with a known set of keys that are used by name. It is also nice because it conveys more intent to the reader.


If you do use objects I might suggest Object.create(null).


+1 Was going to be my response as well...


You can use objects and other things as keys for a Set or Map. As far as I know you can't do that for objects.

    const s = new Set();

    const a = {}, b = {};

    s.add(a);

    s.has(a); // true

    s.has(b); // false


    const o = {};

    o[a] = true;

    o[a]; // true

    o[b]; // true, cause its cast to a string like "[object Object]"
I've also seen Map perform faster than using an object as a Map.


Beware of a gotcha here: object keys are tested for strict equality and not deep equality, in other words add/get must use the same object instance and not just an object with the same keys/values


It's a pretty straightforward way to do things like avoiding duplicates or checking if an item is part of a collection without using quadratic loops or string-keyed dictionary objects.

It's O(1) for the latter (edit: I stand corrected, but probably close, as per spec).

Conversion to and from arrays even preserves order.

So I don't see these two use cases as "showing off", why should anybody do that?


I have only used JS sets in interviews to avoid duplication - more than once, the interviewer has chuckled appreciatively and directed me to not use them (being too easy)


That would be a red flag for me in most cases, as the person being interviewed. If the interview is to gauge my knowledge of Javascript, then using sets should be in my favor since I'm using the most optimized approach to demonstrate I know the language well and can adequately do the job. If it's "not acceptable", then what is the goal there? To wrack my brain as part of some pseudo intelligence test? Shall we break it down to 1s and 0s too?


It can be a point in your favour but also something that you are asked to avoid. You both showed good knowledge and default choices and showed that you can implement a simple algorithm from scratch. Both are valuable points about your skills.

The main "result" of the interview shouldn't just be "does the code work". The process is far, far more important for understanding how you write code.


Fair, and that's actually the opposite of using them to show off, right? :)


I've used them occasionally to clarify the semantics of collections; I like being able to express that some collection of values is unordered and has only unique elements.


Ditto!!!


Damn, in 2024?

Do Java next!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: