Collections In Javascript

Objects

Objects are good for static information, something like this:

const colors = {
    red: '#d10202',
    green: '#19d836',
    blue: '#0e33d8'
}

Not good for dynamic information though. They’re useful if you’re not mutating a specific object — like if you’re building an object in a function and then passing it to another function.

Object.assign

const defaults = {
    author: '',
    title: '',
    year: 2017,
    rating: null,
};

const book = {
    author: 'Joe Morgan',
    title: 'Simplifying JavaScript',
};

function addBookDefaults(book, defaults) {
    return Object.assign(defaults, book);
}

The first object gets updated with the values of the following objects!

How to avoid mutating the first object? Start with an empty object!

const updated = Object.assign({}, defaults, book);

Object.assign doesn’t deep copy.

Object Spread Operator

const book = {
    title: 'Reasons and Persons',
    author: 'Derek Parfit',
};
const update = { ...book, year: 1984 };
console.log(update);

Output:

{ title: 'Reasons and Persons',
  author: 'Derek Parfit',
  year: 1984 }

This works really well! It’s also accepted as part of ECMAScript 2018, so it’s officially part of JS.

Object.entries

Object.entries works, like it does in Python! You can do something like this:

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

Map

Key lookups for objects are linear, but when maps are implemented natively, their lookup time can be logarithmic.

They also don’t automatically convert all key names into strings - they be properly used as HashMaps.

They also have a unified API for things like setting keys, deleting keys, and resetting the dictionary, versus doing these things with the default object notation looks something like this:

function addFilters(filters, key, value) {
    filters[key] = value;
}

function deleteFilters(filters, key) {
    delete filters[key];
}

function clearFilters(filters) {
    filters = {};
    return filters;
}

Which uses a bunch of different ideas and isn’t very clean or predictable.

Map Syntax

let filters = new Map();
filters.set('breed', 'labrador'); // key, value pair
filters.get('breed') // 'labrador'

Shortcuts for setting data

Method chaining:

let filters = new Map()
    .set('breed', 'labrador')
    .set('size', 'large')
    .set('color', 'chocolate');

Array syntax:

let filters = new Map(
    [
        ['breed', 'labrador'],
        ['size', 'large'],
        ['color', 'chocolate'],
    ]
)

Deletion:

filters.delete('color');

Clearing the map:

filters.clear()

MapIterator

Cool generator like thing for iterating over the keys of a map. Way better than using an array.

const filters = new Map()
    .set('color', 'black')
    .set('breed', 'labrador');

function checkFilters(filters) {
    for (const entry of filters) {
        console.log(entry);
    }
}

checkFilters(filters);

Result:

[ 'color', 'black' ]
[ 'breed', 'labrador' ]

Spread Notation in MapIterator

You can do something like this:

const filters = new Map()
    .set('color', 'black')
    .set('breed', 'labrador');
console.log([...filters]);

Output:

[ [ 'color', 'black' ], [ 'breed', 'labrador' ] ]

Returning an updated map (copy)

Spread notation to the rescue again!

function applyDefaults(map, defaults) {
    return new Map([...defaults, ...map]);
}

Spread notation is pretty awesome tbh.

Sets

Convert from a list to a set:

function getUniqueColors(dogs) {
   return [...dogs.reduce((colors, { color }) => colors.add(color), new Set())];
}

The { color } part is pretty interesting: if you have an object with multiple keys, if you want to specifically extract a certain key and then do some operations on it, you can do something like that.

Created from: Modern Javascript Course 202006070113


uid: 202006142245 tags: #programming #javascript


Date
February 22, 2023