Indexed collection can be an Array or TypedArray. Let’s go through each of them.
The most popular and well-known collection of data is an array. An array is an index collection of ordered elements that have their own index and can be accessed by this index. Arrays can contain any data type and even other arrays. Regular arrays are not type-based. This means that you don’t have to define what data type you are going to use inside the array. You can use everything together and anytime you want.
There are several ways to create an array. The easiest and most modern way is to create a variable with a value of empty square brackets. Later on or right away, you can place there any data you need.
Accessing array elements
To excess an array item, you can simply use an index (position) of the target item. Just don’t forget that index starts with 0 so the first element is index 0, not 1.
Destructing is a way of extracting data from an array in the most efficient way. Arrays can be very complex at times and even have several levels.
The most simple way to retrieve elements from an array and very easy for beginners to understand is targeting the elements by index. For example, if you need a specific item, you can count its index and retrieve this element.
Looks easy, right? But let’s say I want to retrieve more.
But what if I have 100 elements? You are going to spend so much time retrieving everything one by one. By using a destructing we can minimize the code and time.
It looks so much shorter and easier now. As you can see I placed new variable names in an array and each variable matches the value in an array by its position. My first variable is apple and the first element was assigned to an apple. There are many tricks and this is not the only thing you can do with destructing.
Image that you want to retrieve only the first value and you want to save the rest separately. It is absolutely possible!
I repeated almost the same logic with a little difference. The first element is saved accordingly, just like before. However in order to save the rest of the elements I am using a rest parameter (the three dots) and a desired name of the variable.
What happens if we don’t use the rest parameter? It will not save the rest of the elements from the array but save the one according to the position (index) and the rest will be simply ignored. Let’s use the exact same example but without the rest parameter.
Another trick that you can use is skipping the specific index. For example, you want to retrieve the first and the third element. To do so, you can write an empty space a comma, and the next variable name.
As you can see, we skipped an orange and moved on to the last element.
Arrays can often be flexible and change a lot. What happens if you add more variables than there are elements in an array? Nothing, it will simply be undefined.
However, it might not be convenient because you don’t want the website users to see any values they don’t understand. Until they are reading my post haha. To solve this issue you can also add a default values which will replace this undefined until there is an actual value.
You might ask if they are so similar why does a typed array exist in the first place? As we already discussed, regular arrays can hold any data which we can manipulate at any time. However, the web keeps developing and there is more usage of heavy data like videos and audio. Such data is much harder to work with for the browser so it needs more time and effort! Of course, this is more complicated than this behind the scenes but all you need to know right now is that typed arrays store raw data that works much faster in the browser hence improving the performance which is vital for heavier and more complicated data.
The typed array is split into two parts — buffers and views. A buffer contains just data (memory) and nothing else while a view turns this data into a typed array by providing a data type of context (a data type that turns data into a typed array), a starting offset, and the number of elements.
In order to use a typed array you need to create an ArrayBuffer and then view it. When creating one you can either create a view first by indicating the desired size and type or you can create an array buffer and then the view that points to it.
The views can be various and a single array buffer can have different views.
Let’s create a view for a typed array with a specific size and type.
We created a view with the type Uint8Array and a size of five. We are going to cover the view types very soon so it’s fine if you don’t understand what it means right now. Let’s see what it shows in the console.
Pay attention to zeros. The five zeros you see is the size we have set previously. But they are empty right now and there is no data yet. Time to save some data there by using an index just like in an array.
Let’s see the console again. Can you guess what will change?
As you see, there is now the number 10 at the index 0 and 20 at the index 3, just as we set it.
Time to create an array buffer first and then the view, so it’s a revered way of a typed array creation.
Looks very similar, right? As you understand, the result is exactly the same.
Typed array views can be different as they can view different numeric types, for example, Int8, Uint32, Float64, and so on. It all depends on what you are working on and what type of data you need to process.
When to use TypedArray
Typed arrays are often used with web APIs. An API is a middleman between the application and the server. For example, when you are registering somewhere and then logging in, all the information is sent back and forth. By using a website you ask an API what you want from the web server.
Browsers have various built-in APIs that are using the typed arrays.
This API also works along with HTML Canvas and uses typed arrays. It provides various methods, objects, and properties to draw and manipulate the canvas element in real time.
XMLHttpRequest Level 2
FileReader is a method of reading the content of a blob or a file. A blob is a file-like raw data read as binary data or text. And a file is a specific kind of blob. This is where typed arrays come into play as we have to work with binary data.
You can convert typed arrays from one type to another by using ArrayBuffer and you can also convert a regular array into a typed array.
To convert an array into a typed array you can use a built-in method typedArray.from() that accepts three parameters typedArray.from(source, map, arg). The source is a target array, the map is an options parameter for a function that is called on each element and the arg is the optional value used in the map function.
Converting from one typed array to another works just as simply. You simply target the desired typed array view and pass the typed array you want to convert.
A map is a simple key-value pair object where you can iterate through elements in insertion order. Keys always need to be unique just like an index. To create a map you can use a map constructor and then add the desired elements by using a set method. The key name needs to be a string and a value can be any data type.
In order to access the key, you can use a get method and the key name. If you use a key that doesn’t exist, it will return an undefined.
Maps have various built-in objects including the set and get which are the most used ones.
This method removes all existent key-value pairs and resets the map.
The delete method returns true if the key existed and has been removed and false if it doesn’t exist.
Returns a new iterator object with all key-value pairs. Iterator means that you can iterate over it, and loop over each key-value pair.
This method is very similar to the previous one and also returns an iterator object that includes only keys.
And the same works for this method but instead of keys it returns the values of the object.
This method works similarly to the forEach method in arrays. It executes a function for each key-value pair in the map in insertion order.
The has method checks whether there is a value associated with the key that we are passing into this method. So it returns either true or false. Note that you need to pass the key, not the value.
Iterating over maps
To iterate over maps you can use a for…of loop. To target both key and value, a very easy way to do so is the usage of destructuring.
The same can be achieved using an entries method on the maps object. Compare them and find the difference.
If you want to work only with the keys, you can use another method for keys.
And the similar for working only with the values.
Difference between maps and weak maps
In weak maps, the keys can only be objects (or non-registered symbols) while values are more flexible.
However, what is the reason that it’s called weak? The reason behind it is the fact that these key objects are a target of so-called garbage collection.
In weak maps, you also don’t have methods to access the keys as they are weak. Weak maps hold the reference to the key, not the key itself.
You cannot iterate over the weak map like you can with the map but they do share some similar methods like get, set, delete, and has.
Why do we need weak maps?
Unused memory can take place in different situations. For example, unused event listeners that are attached to specific elements. An element might be removed but the unused event listener is still there. Now imagine a lot of event listeners like that that use a memory but we don’t even need them. Other causes of memory leaks can be callbacks, timers (e.g. setTimeout), closures, and large data structures.
For instance, imagine that you want to track how many times a user clicked the ads on your website.
First, we will create a regular map where the user will be the key and the value will be how many times they clicked the ad. When the user leaves the website, we don’t need the information about the clicks anymore.
Once the user object is gone, the object will remain in the map as a key so we manually would need to clear that map because it is not garbage collected and takes up the space in the memory. If you have a bad website maybe hardly anyone visits it but imagine if you had a lot of visitors. To test this, let’s log the map to the console and see what it contains.
As you see, even though we said that the object of the user is null (“empty”) the map still holds the information about the user.
This is where a weak map comes into play. A weak map is going to “weakly” refer to the user object which will allow the process of garbage collection. We are simply going to replace a map with a weak map and then see what happens to the information about the user once we try to clean it.
As you can see, there is no more user object and a weak map got garbage collected! So awesome, right?!?!
Set is another keyed collection that consists of values. What makes this collection special is the fact that you can have only unique values and it’s impossible to add any repetitive data. When you try to add a repetitive value, it will keep the one you added first.
Let’s create a simple set to understand how it works.
Next, I am going to try to add the repetitive value apple. What will happen?
Nothing. There is not going to be added anything. The repetitive value is not going to be added and the old one removed. It will be ignored. The apple result you see is the old value, not the new one. Because elements in the set are placed in the insertion order so if it was the new value it would be the last, not the first.
Just like maps, sets also have various methods. Compared to maps we use add instead of set to add new values.
This method removes all existent values and empties the set. But when you check an empty set it returns undefined. Instead, you can use a size property and it will show 0 when it’s empty.
As the name suggests the delete method removes the value that we indicate.
This method creates an iterable object of key-values where keys are equal to values in this case. So it becomes something similar to a map
This method returns an iterable object containing values. Set.prototype.values() is exactly the same.
Just like in a map, has returns true or false depending on whether it has a value we passed to the method.
This method executes a function for every single value in their insertion order.
Iterating over sets
You can iterate over sets using a for…of loop.
A weak set compared to a regular set is a collection of objects while sets can contain any data type. A weak set, just like a weak map holds information “loosely”, for the purpose of temporary storage. Just like a set, a weak set also has unique elements and they are not repetitive. The weak sets just like weak maps are also used for garbage collection so make sure not to skip the topic about garbage collection that I have mentioned earlier.
A weak set also supports methods like add, has, and delete however it cannot be iterated over and doesn’t have a size property. A weak set usage is very good for the yes/no situation when let’s say you are tracking your users and you check how many people are online right now. But when they log out you don’t want to save the objects of the users. Just like with the weak maps, similar logic works with the weak set as it’s garbage collected.
Sometimes, you might want to target all the buttons on the current page. The collection of these buttons becomes a DOM collection which is an array-like collection. It’s more similar to an index collection though it looks like an array.
Let’s check how many span tags there are on the main page of Amazon. To achieve that we can target span elements by using document.getElementsByTagName(“span”). This will target all the spans.
Wow, so many spans!! And here we got all the spans in just one line.
I hope you learned or re-learned something about indexed collections that are based on index values, keyed collections that consist of key-value pairs, and DOM collections that are simply groups of HTML tags. Of course, there is much more to learn about collections however if you are just getting started I believe this is somewhat enough for the start!