New Map and Set methods in JS

Map vs Set - Concepts, Analogies, and Core Differences

The speaker opens with an agenda overview covering old and new Map and Set features, browser support, and bonus array methods. Set is introduced using a guest list analogy (unique values, quick membership checks) and Map using a library analogy (ISBN codes mapped to book details). The fundamental distinction is clarified: sets are one-dimensional collections of unique values, while maps are two-dimensional key-value structures.

Sets in Practice - Creation, Deduplication, and the Reference vs Value Pitfall

Using a bouncer named Brutus as a running example, the speaker demonstrates creating a Set from an array and shows how it automatically eliminates duplicates. The speaker also shows that any iterable, including strings, can be used to construct a Set. A critical caveat is introduced: object deduplication does not work as expected because JavaScript compares object references rather than values, a common source of bugs.

Maps in Practice - Core Methods with a Library Scenario

Through a librarian-managing-books storyline, the speaker demonstrates the full suite of existing Map methods: creating a Map with ISBN keys, and using set, get, has, forEach (to migrate books from a boolean fiction field to a tags array), delete, keys, values, and clear. Each method is shown with a concrete scenario, such as a government audit requiring book lookups and a library fire prompting a clear of the entire collection.

Existing Set Methods and JavaScript Browser Compatibility

The speaker covers all pre-existing Set methods - add, delete, has, size, forEach, and clear - using guest list management and a palindrome-filtering example to illustrate each. The segment then shifts to explaining the browser compatibility baseline system: widely available features safe to use, newly available features requiring caution, and limited availability features best explored via polyfills. The speaker advises using polyfills now to adopt new features early and remove them later as browser support matures.

New Set Methods - Mathematical Set Operations

The speaker walks through seven new Set methods recently added to JavaScript, all illustrated with Venn diagrams and a party management storyline: union (merging two guest lists), intersection (finding guests attending multiple events), difference (identifying troublemakers on a list), symmetricDifference (guests on one list but not both), isDisjointFrom (confirming no overlap with a banned list), isSubsetOf (verifying a small group is within the main list), and isSupersetOf (confirming VIPs are on the main guest list).

Grouping with Map.groupBy and Object.groupBy

The speaker introduces the new groupBy method available on both Map and Object, using a library restocking scenario to demonstrate grouping a book inventory by whether copies fall below a threshold. The key distinction is highlighted: Map.groupBy supports object keys (enabling richer grouping metadata), while Object.groupBy is limited to string keys. The speaker also cautions that grouped objects are shared by reference with the original iterable, not deep-copied.

Non-Mutating Array Methods - toSorted, toReversed, and toSpliced

The speaker closes with a bonus on new 'to'-prefixed array methods that return a new array instead of mutating the original: toSorted, toReversed, and toSpliced. A live comparison shows that the traditional sort modifies the original array in place, while toSorted leaves it unchanged. The speaker cautions that these methods still do not perform deep copies, so object references inside the arrays remain shared between the original and the result.

Alright. First, we're gonna go through what is a map versus what is a set. What's the difference between the two? And then we're gonna go through a demo. We're gonna compare, map and set, how to use them, the basics. We'll go through the old map features and the old set features, and we'll talk about the browser support, some of these new things on the web. And then we'll go through the new set features and map has a new group by feature.

And then we'll do a bit of bonus in place array stuff. So I like to think of a set as a guest list. So you can't have duplicate guests. Order is kind of irrelevant. You just wanna know if someone's in the guest list or not. You can quickly check if someone's on there, add people, remove people, and count how many there are.

And you could use names or mobile numbers or even JavaScript objects. Whereas I like to think of map as a library. So you have unique book IDs. It could be the ISBN of that book, and each code responds to the book itself. So it might be the title, it might be an object with book details, you've got a sort of a key value relation there.

And order is mostly irrelevant again. You just want to match the book ID to the book and you can quickly check if you have a book on hand, add, remove, update or count, and you can store information about the book. So they're very similar, but what what's the actual difference?

So a set is just a bunch of unique values, whereas a map is like a set, but each value is actually key, which is pointing to the actual value. So sets are sort of one d and maps are two d. So here, imagine we've got a, bouncer called Brutus, and he wants to develop a JavaScript application to manage his guest list.

So we can see here we're creating a new set and we've got a few names here. We've got Mike Main, Sally Saltwater, some random people, and we can log this guest list and that's basically what we've created there. We've got a set representation in JavaScript. And if we add the same person again, like if I add Sally Saltwater again, it should remove the duplicate.

And you can see here, we only get one Sally saltwater. I'm running this inside Jupyter notebooks, by the way, in Versus Code, so that's how I get this live result here. You can also use strings to set up a guest list. Sorry. I've just got Vim working here, which is a bit of a mess. So not only can you use an array, but you can use strings. Any sort of iterable object in JavaScript, you can pass in when you're creating a set.

So I could use a string here, which is very cursed, but you can see it doesn't duplicate any of the letters because it automatically handles all of that for you. So some people actually use a set just to remove duplicates and then turn it straight back into an array or an object. But the issue with this is also if we set out if we use objects within our set, because of reference versus value, it actually doesn't remove the duplicates.

This is a classic issue in JavaScript. We've got reference versus value. So primitives like a string or a number fine in a set, they'll be removed duplicates will be removed, whereas objects, it's kind of like instead of having the actual primitive, you have a key to a locker with the primitive. And so you might have two different keys, and so they're both in the set, but they point to the same value.

So that's something that might trip you up with a set. Whereas a map, let's say we've got a librarian and they're very scared of databases, so they decide to use JavaScript to manage their book collection. And let's say we're creating a map where we've got these very realistic ISBNs and then just the title of the book.

So we can do that with just new map similar to set, and that'll create a map representation in JavaScript for us. So there's all our books there. And it should replace duplicates. So if I change in here, just do how oops. Ah, thank you. Live coding.

So we've replaced four four seven with another value. So you always have one key to one value. So let's move on with this example. Let's say this librarian wants to add a new book. Map has the set method. This has existed for a while. So we can set a new ISBN and a new title, and that should be added to our map right there.

We've also got the get method, so we can retrieve a value. We could get ISBN one two three, and it should return that title there. I should have removed this warning before I started. Okay. The next one, let's say the Australian government is conducting an audit. There was a whippersniffer attack, and they're suspending all whippersniffer related books. So we have to report whether we have a book ID of four four seven or 889.

So we can use the has method here. So we can check we don't care, what the title is, we just want to check if we have the book on hand. So if we run this, we have 447 in our map, but we don't have 889, so we get true and then false. Okay. So we've improved our map.

We've got tags now, so well, we've got a boolean for fiction or nonfiction, but we want to move to tags. How could we automate this? Say we've got a huge library. So we can use the for each method. So for each is sort of like a higher takes a higher level function, so we can just pass in a immediately invokes one here, and we're checking if we're a fictional book.

Actually, no. We're checking if we don't have fiction defined on one of our books, so I could comment this one out. VIM extension and Jupyter notebooks don't like each other at all. Oh, god. There we go. Alright. So let's say we comment out one of the values, it'll still work here. So we're returning out if fiction is undefined, and we're setting we're replacing the map item.

So we're setting the key, we're setting the value, so for each iterates through each entry in our map. We can get the value of the key and the key itself and the map. So with those values, we can set a new value for each book. So we'll set the key.

Title is pretty much the same, but now we want to do tags instead of a boolean. So here, we're just checking based on the boolean, which tag do we want to add to the book. And you can see here if we log this, there we go. We've got tags with an array of tags instead of a boolean. So foreach, very, very powerful.

I really should have removed this warning. Okay. The Australian government got back to us. They said we're banning all Wipersynfa related books. So now we've to remove them from our library. So we can use map dot delete. So we'll basically go through and delete four four seven because that's the one that we had related.

So you can see it here, we've got our map with the banned book, and then we've deleted it. Alright. Now we wanna back up our library just in case there's a disaster. But we wanna save a few kilobytes, so let's only back up the ISBNs that we have on hand for insurance purposes.

So with that, we can just do our map dot keys, and that will just give us all of the keys, not the values. And if we log that there, there's our book collection. Okay. Say a friend asks what books we have on hand, but the friend is very scared of ISBN codes.

We can just log the values rather than the keys, although I didn't update this. So we just do our map dot values, and now we've got all of the actual objects without the keys. And I went down a rabbit hole of iterators, and I think that's a talk in its own, but you can essentially turn a map or a set back and forth, to an iterable object in JavaScript. And there's slight features and variants, but, you can essentially do the same thing with the built in map and set methods.

Okay. So luckily, we recorded all of our books for insurance purposes because the library just burnt down. And so with the new insurance money, we'll buy a new book collection. But since we used const to define our library, we can't reinitialize it. So we want to clear our library. We can do the map dot clear method, and you can see here we start off with our book collection, and then we've cleared the entire thing, and there's nothing left in the collection.

Alright. Back to sets. So what already exists in sets? Like map, we've got an add function, so it can essentially create a new set of unique values. Say we wanna add someone to a guest list afterwards, if we log it, we can see we've added this person to our existing list. And you can actually chain these, which is pretty cool, in the same line.

But what if we wanna remove someone? We use the delete method similar to map where we can just delete a person from our list and they're no longer in the invites. But now we've been asked to replace the, the harp player with a trombone player for our event.

So we've been asked to check whether we have done this and so we can use the has method. So we wanna check, do we have the harp player and do we have the trombone player? And you can see that we have removed the heart player and we have the trombone player. So if you wanna quickly check if you have a value in your set, you can easily use has.

But now our bouncer wants to brag to his mate about how big this event is, and so he can use set dot size to do so. So size should return the number of unique items in your set. So everybody's arrived. Our bouncer is a little bored, so he sets up another JavaScript app to calculate palindromes, so where words spell the same word if they're in reverse.

So we've got a little function here that removes palindromes, removes non palindromes from our set. So we've got a bunch of words in here. We go through for each and we pass in our function. So similar to math, we've got the value and the key. Now the key's there just for symmetry with map.

It's pretty much the same as the value, and we've got our set object there as well. So we'll just check if we're a palindrome or not and delete the value if we're not. So you can see there we've got two palindromes in our list. Okay. We're ready to clear the list, ready for our next event.

So same as map, we can just do set dot clear, and that'll clear everything out of our set. Okay. So those are all the value all the methods that already existed on MapInset. So that's what we'd we've had since around 2015. So those are baseline widely available.

So I think it was Chrome pushing this about a bunch of browser developers. An easier way to to figure out whether you should use a new feature or not, we've got baseline, which means it's been around in all major browsers for quite a while. People have probably updated their browser and have this feature, so you can assume that it's safe to use.

You've also got baseline, which means that it's in all the major browsers, but it's not yet ready to use because people might not have updated. They might need to buy a new iPhone to be able to update Safari to the latest version. You might have to wait a while to use these features. And then limited availability is perfect for playing around with new features.

They might be in Chrome usually, but not other browsers. Sometimes even Safari beats the others to things like Apple wanna sell retina displays and they wanna introduce new colors, so they'll add those sort of features first, whereas Chrome will add more sort of app features and and complicated JavaScript stuff first usually. So limited availability means it's only in a few browsers and you should just really play around with it at this stage or use a polyfill. So set and map all these new methods have polyfills.

So if you want to use them today, even though they're sort of baseline newly available, you could add a polyfill so that you can use it today. And then down the line when it's in pretty much everybody's browser, you can remove that polyfill and you've already been using the latest JavaScript. So yeah, I updated from Node Notebook in these examples to Jupyter because I started using Node Notebook for the old set methods and it worked, but then I used the new ones and it actually wasn't in this Versus Code extension yet.

So another reason you might wanna use a a polyfill or use caution with these new features is that they're not everywhere yet. So I upgraded to Jupiter and they supported a newer node version. So you wanna use the latest node version, obviously, if you wanna use these new features. So let's go back to our party.

We're rehired at another one, but the host wants to invite all the friends from the previous event. So how could we add our guest list for the new party to our guest list for the previous party? Well, for that, we can use the new union method on set. So we've got guest list a and guest list b.

We can easily add both by using a union right here. So you can see we've merged both sets together, and here's a nice Venn diagram for union. We've basically got all of a and all of b, all the overlapping into one set. But now the host suspects that some people have been invited to a rooftop party. We need to identify who's both on this party list and on our party list because they might be bouncing back and forth between events and we don't want that.

We want to we want to keep things calm. So we have our our list of these rooftop partiers and then we have our existing guest list and we can use the intersection method to figure out who is on both our list and on this rooftop party list. So you can see here we've got two people that are on both lists, our intersecting section on the Venn diagram, so we can easily figure that out with this new method.

But now we've got some troublemakers who have shown up, and we need to make sure none of them are on the guest list. For this, we can use we've for this, we've got a set of our troublemakers and we can use the the difference method to figure out who these troublemakers are, who are on our list. I think I read that wrong.

Alright. So we're making sure that none of them are on the guest list. So here we've got our Venn diagram of a, which is our guest list, and then b, which is our troublemakers, or actually the other way around. So basically checking if these, troublemakers have shown up. We want to create another party now.

We want to do sort of an oddballs only night. So we want to invite people who are on one list but not on both. So for that, we can use the symmetric difference method. So we've got our existing guest list and we've also got this costume party that occurred. So we want to check for people that are either in the guest list or in the costume list, but not in both.

For So that, we can actually use symmetric difference. And there's our Venn diagram there. So they're either in a or b, but they're not in both. And for that, we can figure out, who's in one but not both, and that's our list there. These are all very straightforward as you can sort of tell.

So some pranksters have been banned from trying to sneak into the venue, so we wanna check, make sure that there's no overlap between, these pranksters and our guest list. We want to make sure they're not in there. And for that, we can use is disjoint from, and that will return a boolean, true if these people are not in our list, and false if they are.

And you can see here, luckily, we don't have any pranksters in our party. Alright. A small group of guests arrive. They're claiming to be on the guest list. So a quick way we can check if they are is we've got the set of these people, and we can do is subset of guest list. So if these people are within our guest list, and there's your diagram there, if they're within our largest set, then return true, and if they're not, then we'll return false.

And luckily, both of them are on the list. Alright. Now the organizer is setting up a VIP thing, within this event. So we wanna check if our VIPs are on the main guest list. So we've got a list of VIPs here, and we wanna check, are they in the main guest list?

So we can do guest list dot is superset of and then our VIP list. So is our guest list a a superset of b? And luckily, everyone in our VIPs is also a guest of the main event. Let's get back to sets back to maps.

So those are all the new set methods in JavaScript. There's a new map method, group by. So let's say go back to our library example. We're now managing a much bigger library. And some books have well, most books have multiple copies, and we wanna check if we haven't got enough copies of each book.

So we've got a list a map of books here. Well, actually, we've got a array of books here, and then we've got a threshold. So we want at least six books on hand. We've got these consts, so we're going to sort by whether we need to restock or whether we've got sufficient quantity on hand.

So we could use this function here, map dot groupby. So we want to group by whether we need to restock or whether we're sufficient. We pass in our map array, which is our book inventory, and this will return a map for us. So we wanna go by each copy, and for each copy, if we don't have enough, we wanna restock.

Otherwise, we've got sufficient quantity. And if we log this, we'll get the two books that don't have a quantity of six. And if we log, log the actual map that's returned, if Vim lets me, If anyone knows how to do Jupyter notebooks inside of VIM itself, please come and see me after this.

Oh my god. It logs the entire map. So we'll have a map entry for restock and a map entry for sufficient. So with maps, you can actually use an object as the key. So there, we've actually got an object with restock to true as the key for things we do need to restock and an object with restock set to false for things that we don't.

Whereas we can also use group by on the object in JavaScript as well as the map. So here we're doing objects dot group by dot group by, but we can't use objects as keys for an object. So in this case, we're just filtering into the restock and sufficient strings rather than an object, which means the syntax here isn't as cool. But if we log this, we can see that we get the same output, and here we've got an object, returning the sufficient quantity books and the books that we need to restock.

So group by, it's on the objects, but it's also on the map, and it's based on what return type you want. Both of them take an iterable that they go through. One thing to note with that function is that the objects are shared between the iterable that you pass in and the map or object that you get back.

So, again, back to reference first value, holding the values themselves or holding a key to the value, we gotta be careful, which brings us to these new array functions prefixed with two. So now you can actually use these array functions without editing the array in place. It creates a new array with completely new with the same objects if you pass in objects.

So this is a really cool new ability on the web where normally if you sort an array, it will change the array itself but also return it. So if I log this here, you can see we've we're using the new to sorted. So we have our original array, which is not sorted, and then we've got our sorted result.

But if we use the old sort method, it actually changes both. So sort will actually in place sort an array, whereas to sorted will just return you the sorted array. But an issue with this is that if you pass in objects, like I said earlier, it will actually pass the same object.

So reference versus value is not solved here. I just want to caution people. So like if I had objects in this array, they would still be the same objects between both, so it doesn't do a deep copy. So if these were objects, they would actually be the same keys as the existing array.

But these are really cool now in JavaScript bonus, would you like, that we can now sort without sorting in place. We've also got toReversed and toSpliced, which do a similar thing for those methods. Any questions?

Agenda

  • Map vs Set
  • Demo 1: Map and Set
  • Demo 2: Old Map Features
  • Demo 3: Old Set Features
  • Browser support
  • Demo 4: New Set Features
  • Demo 5: GroupBy
  • Demo 6: in-place array methods

Set - Guest List

  • No duplicate guests
  • Order is mostly irrelevant
  • Quickly check / add / remove / count
  • Could use names, mobile numbers, even objects*

An image of a bouncer holding a clipboard represents a Set used as a guest list.

Map - Library

  • Unique book ID (key) for each book (value)
  • Order is mostly irrelevant
  • Quickly check / add / remove / update / count
  • Can store titles, object with book information etc.

An image of a person holding books represents a Map used as a library catalogue.

Map vs Set

A historical illustration shows two opposing groups arranged on either side of an open field, providing a visual metaphor for the comparison.

Set

Unique values

Map

Unique keys → values

The bouncer represents a Set of unique guest values, while the person holding books represents a Map whose unique keys point to values.

Demos 1-3

Map and Set fundamentals

Set construction

let guestList
guestList = new Set(['mike maine', 'sally saltwater', 'tim trombone', 'dylan dominic'])

Map membership

console.log(library.has(447)) // true
console.log(library.has(889)) // false

Set membership and addition

guestList.add('Mandy Maze')
console.log(guestList.has('harry harp')) // false
console.log(guestList.has('tim trombone')) // true

A live-coding sequence introduces established Map and Set operations through a guest list and library catalogue. Constructing a Set from an iterable removes duplicate primitive values, while two separately created objects remain distinct because Sets compare object references. The Map examples create keyed book records, test whether ISBN keys exist, iterate over entries to transform book metadata, and obtain keys for backup. The Set examples then add, query, delete, iterate, count, and clear guest entries. The sequence concludes by previewing union(), which combines two guest lists into one six-person Set without duplicating their shared guest.

Baseline badges

Baseline Widely available

Features have a consistent history of support in each Baseline browser for at least 2.5 years.

Baseline 2022 — Newly available

Features work in at least the latest stable version of each Baseline browser, but may not work with older browsers and devices.

Limited availability

Features are not yet available in all browsers.

Browser indicators accompany each Baseline category to summarize support across Chrome, Edge, Firefox, and Safari.

set.prototype.difference

ES Proposal spec-compliant shim for Set.prototype.difference.

npm i set.prototype.difference

61k downloads/month

An npm package page presents a polyfill that supplies Set.prototype.difference when the native method is unavailable or noncompliant.

Baseline badges

Baseline Widely available

Features have a consistent history of support in each Baseline browser for at least 2.5 years.

Baseline 2022 — Newly available

Features work in at least the latest stable version of each Baseline browser, but may not work with older browsers and devices.

Limited availability

Features are not yet available in all browsers.

Browser indicators accompany each Baseline category to summarize support across Chrome, Edge, Firefox, and Safari.

set.prototype.difference

ES Proposal spec-compliant shim for Set.prototype.difference.

npm i set.prototype.difference

61k downloads/month

An npm package page demonstrates that a polyfill can expose difference() as a Set method until native runtime support is sufficient.

Node notebook → Jupiter

New Set methods, Map.groupBy(), and copying array methods

Set composition

guestListA.union(guestListB)
troubleMakers.difference(guestList)
guestList.symmetricDifference(costumePartyList)
smallGroup.isSubsetOf(guestList)

Group inventory by restocking status

const sortedInventory = Map.groupBy(
  bookInventory,
  ({ copies }) => copies < RESTOCK_THRESHOLD ? restock : sufficient
)

Sort without mutation

const originalArray = [1, 3, 5, 2]
const sortedArray = originalArray.toSorted()

The live-coding sequence demonstrates the newer Set composition and relationship APIs. union() combines two guest lists; intersection() finds guests shared with another event; difference() retains entries present only in the calling Set; and symmetricDifference() retains entries found in exactly one of two Sets. Boolean relationship checks then determine whether Sets are disjoint, subsets, or supersets. Next, Map.groupBy() partitions book objects by a callback-derived key, producing a restock group containing “The Starry Scroll” and “The Phoenix Codex.” Finally, toSorted() returns [1, 2, 3, 5] while preserving the original [1, 3, 5, 2]; replacing it with sort() mutates the original so both arrays become sorted. toReversed() and toSpliced() are noted as related copying methods.

Technologies & Tools

  • Array.prototype.toReversed
  • Array.prototype.toSorted
  • Array.prototype.toSpliced
  • JavaScript Map
  • JavaScript Set
  • Jupyter Notebooks
  • Map.groupBy
  • Node.js
  • Object.groupBy
  • Set.prototype.difference
  • Set.prototype.intersection
  • Set.prototype.isDisjointFrom
  • Set.prototype.isSubsetOf
  • Set.prototype.isSupersetOf
  • Set.prototype.symmetricDifference
  • Set.prototype.union
  • Vim
  • VS Code

Standards & Specs

  • Baseline
  • ISBN

Concepts & Methods

  • Palindrome
  • Polyfill
  • Reference vs Value
  • Venn diagram