Learn JavaScript in Construct, part 9: Data structures

19

Index

Features on these Courses

Stats

5,456 visits, 11,434 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY-NC 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 19 Nov, 2021. Last updated 16 Dec, 2021

Map

In JavaScript, a Map is a lot like a set, but inserted values are actually keys with an associated value. It's similar to object properties which we covered in part 7: each property has a name and an associated value. Indeed objects can be used similar to a map, since properties can be added, removed, retrieved and so on. However maps are a better solution if you need a dynamic set of keys. Firstly you can use any type of value for keys, including numbers and even objects, which is not possible with object properties which must be strings. Secondly in JavaScript objects have some built-in property names and overwriting them can cause problems. Maps have no such built-in key names so this problem never occurs with maps.

Similarly to sets, a new empty map can be created with new Map(). However there is no add() method - keys and values are inserted with set(key, value). Then you can use get(key) to return the value associated with a key. The example below demonstrates using a map to store a description for an emoji.

// Create a new empty map
let myMap = new Map();

// Add three keys for emoji and their associated description
myMap.set("😀", "smiley face");
myMap.set("👽", "alien");
myMap.set("🦄", "unicorn");

// Show the map in the console
console.log("myMap is: ", myMap);

// Retrieve the description for each emoji
console.log("Value for 😀: ", myMap.get("😀"));
console.log("Value for 👽: ", myMap.get("👽"));
console.log("Value for 🦄: ", myMap.get("🦄"));

As shown above, if you call set(key, value) with a key that does not exist in the map, it will add it. However if you call set(key, value) for a key that already exists, it just replaces the value for the key.

If you call get(key) for a key that does not exist in the map, it will return undefined, similarly to accessing a non-existent object property.

A map can be created with some initial keys and values as well. This is a little more complicated than with a set: each entry in a map is actually a key and a value, which is two values. So you can create a map using an array of two-element arrays, where the first element is the key and the second element is the value. The next example demonstrates adding the same keys and values as the previous example, but by creating a map with initial keys and values.

let myMap = new Map([
	["😀", "smiley face"],
	["👽", "alien"],
	["🦄", "unicorn"]
]);

console.log("Value for 😀: ", myMap.get("😀"));
console.log("Value for 👽: ", myMap.get("👽"));
console.log("Value for 🦄: ", myMap.get("🦄"));

As with sets, there is also a size property with the number of keys, a has(key) method to test if a key is in the map, a delete(key) method to remove a key and its associated value from the map, and a clear() method to remove everything.

let myMap = new Map([
	["😀", "smiley face"],
	["👽", "alien"],
	["🦄", "unicorn"]
]);

// Delete a key
myMap.delete("👽");

// The size is 2, as one of the keys was deleted
console.log(`myMap size is ${myMap.size}`);

// true
console.log("myMap has 😀: ", myMap.has("😀"));

// false (it was deleted)
console.log("myMap has 👽: ", myMap.has("👽"));

Iterating a map

Entries in maps can be iterated with a for-of loop, similar to sets. However you can iterate it in different ways: you can iterate just the keys, just the values, or both at the same time. To iterate just keys, use a for-of loop with myMap.keys(). To iterate just values, use a for-of loop with myMap.values(). The following example demonstrates both.

let myMap = new Map([
	["😀", "smiley face"],
	["👽", "alien"],
	["🦄", "unicorn"]
]);

// Iterate map keys
for (let key of myMap.keys())
{
	console.log(`Map key: ${key}`);
}

// Iterate map values
for (let value of myMap.values())
{
	console.log(`Map value: ${value}`);
}

Note that as with sets, this follows insertion order.

It's possible to iterate both keys and values at the same time. This involves new syntax though. We want to use a for-of loop with two values per iteration, which we can do using square brackets to declare two variables in the for-of loop. The thing to iterate has also been changed to myMap.entries(), which iterates both key and value.

let myMap = new Map([
	["😀", "smiley face"],
	["👽", "alien"],
	["🦄", "unicorn"]
]);

// Iterate both keys and values
for (let [key, value] of myMap.entries())
{
	console.log(`Map key: ${key}, value: ${value}`);
}

The for-of loop could also be written for (let [key, value] of myMap), i.e. without the call to .entries(), as the default if you don't specify something else is to iterate entries.

The let [key, value] syntax is part of JavaScript called destructuring. It's another fairly complex area we won't go any further in to right now, but we covered it briefly here just to demonstrate how you can iterate both keys and values in a map at the same time. For now, it's worth pointing out the similarity to how maps are created with two-element arrays for each key and value, e.g. ["😀", "smiley face"]: the for-of loop will place the first element in the first variable, and the second element in the second variable.

Converting to an array

Similar to sets, maps can also be coverted to an array with [...myMap]. This creates an array in the same format used to initialise a map: an array of two-element arrays with the key and value.

let myMap = new Map([
	["😀", "smiley face"],
	["👽", "alien"],
	["🦄", "unicorn"]
]);

// Convert map back to array
let asArray = [...myMap];

// Log array to console.
// This is the same format as the map was
// initialised with, i.e.:
// [
//	["😀", "smiley face"],
//	["👽", "alien"],
//	["🦄", "unicorn"]
// ]
console.log("Map converted to array: ", asArray);

Conclusion

In this part we've covered:

  • Creating arrays, accessing array elements, and reading the array length
  • Iterating arrays with both for loops and for-of loops
  • Adding and removing array elements
  • Creating sets, adding and removing set values, and reading the set size
  • Iterating sets, and converting sets back to arrays
  • Creating maps, adding and removing keys and values, and retrieving values from keys
  • Different ways to iterate maps, and converting maps back to arrays

These data structures come in useful with day-to-day programming in JavaScript, so it's good to get familiar with how they work. In particular arrays are very common, so if you want to focus on one area, focus on them.

We've touched on a few built-in features of JavaScript in this guide so far. In the next part we'll focus on covering more built-ins, including some of the many features that browsers provide.

Learn more

If you want to dig deeper, you can learn more about the features mentioned in this guide at the following MDN Web Docs links:

Part 10

When you're ready to continue, head on to the next part at Learn JavaScript in Construct, part 10: Standard library!

  • 3 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • Love these tutorials, many thanks!

  • What made you guys to change your mind, in such odd manner? Before there has been multiple statements that scirra is not there to teach users JS and especially base JS.

    While I can see this opens up huge market and new opportunities with schools and other people. And could level up scirra with army of gamemaking toolsets: editor, runtime, events, JS, animating with meshes, art and more

    If something similar is on verge to be made, i hope C3 does not suffer and left aside.

  • Greate job Ashley, keep going!