DEV Community

Cover image for JavaScript Map is getting upsert!

Posted on • Originally published at

JavaScript Map is getting upsert!

This post originally appeared on

Let's introduce a new (potential) piece of syntax in JavaScript!

What is Map?

Map is a data structure in JavaScript that you may not have heard of! When you think of map, you probably think of

But Map is different. A Map is an object in JavaScript that holds key-value pairs.

Wait a is that different than an Object?!

They have some similarities. In fact, it was not uncommon to use an Object in place of a Map before Maps were added to the language. However, there are also differences, mainly:

  • A Map has no prototype, so there are no keys at all unless you create them
  • Map keys can be anything, including functions or objects
  • Map remembers the insertion order of your keys
  • Map comes with a size() function
  • Maps are Iterables
  • Maps can be more performant when frequently adding or removing key-value pairs

Adding values

You can create a Map and add key-value pairs using the set function.

let example = new Map()
example.set('test', 'value')
// example is Map { 'test' => 'value' }
Enter fullscreen mode Exit fullscreen mode

However, if you set something with the same key, the value will be overwritten.

example.set('test', true)
// example is Map { 'test' => true }
Enter fullscreen mode Exit fullscreen mode

If you want to operate on a specific key you need to make sure it's there, add it if it isn't, and then operate on it.

if (!example.has('test')) {
  example.set('test', 'new value')
Enter fullscreen mode Exit fullscreen mode

And this isn't the only situation like that. You may only want to insert a key if it's missing, only update if it's present, etc. It'd be nice to not have to do existence checks and use set and get all the time.

In comes upsert

upsert makes this easier!

upsert is a function on the Map prototype. It takes three arguments.

The first argument is the key that you want to use.

The second is the function you want to operate on the existing value, if found.

The third is what you want to happen if the key does not currently exist.

So our previous example becomes this.

  .upsert('test', undefined, () => 'new value')
Enter fullscreen mode Exit fullscreen mode

In this case, we're leaving the existing value alone if it already exists, thus the undefined.

Alternatively, we have this example.

example.upsert('test', old => old.someOperation(), undefined)
Enter fullscreen mode Exit fullscreen mode

Here, old is equivalent to map.get('test'), and we're operating on it. If the key doesn't exist, we do nothing.

Seeing these two examples it becomes clear that there are a number of different possibilities for using upsert.

TC39 Stage 2

This proposal is currently in Stage 2 of the TC39 process. If you're interested in participating in that conversation, please do!

Top comments (9)

drmandible profile image

Is this different than assigning new values with spread operator?

laurieontech profile image

The spread operator is not valid inside Map's set function so far as I am aware.

omenlog profile image
Omar E. Lopez

Thanks for share it, that is a very good addition. One question:

What do you mean by Map doesn't have prototype at all ?

I did a little test on my machine an got this


craigmc08 profile image
Craig McIlwrath

I believe he misspoke. His comparison was that, when using a plain Object as a map, you have to worry about the keys from the prototype chain. When using a Map, there are no keys already defined in the Map. A Map object is still and object and still uses the prototype chain to define itself.

jenc profile image
Jen Chan

Wait... this is stage 2 so it's not out yet right?

laurieontech profile image

Yup! That’s why I note it as a potential piece of syntax.

ben profile image
Ben Halpern

This is really great news

sargalias profile image
Spyros Argalias

Very nice :). Looks quite convenient!

flexjames profile image
James Ma

So cool, that’s for the post!