NodeJs

Iteration

For...of Loop

Sometimes refered to as an Iterator-based loop or a value-based loop it does not provide the index of the item in the list. Used when you only care about values

const items = ["hello","world"]
for(const item of items)
{
    console.log(item)
}

Index-Based Loop

Index-based loops expose the iteration counter, while for...of loops iterate directly over values in an iterable. This is sometimes refered to as a C-style for loop or a counter-controlled loop. It is used when you need access to the index of the item in the list

const items = ["hello","world"]
for (let i = 0; i < items.length; i++) {
    const item = items[i];
    console.log("item no. "+i+" is "+item)
}

Array

length

Returns the number of items in an array.

const list = [1, 2, 3];

const length = list.length;

console.log(length); // 3

Copy (Shallow)

Creates a shallow copy of an array. Changes to the new array do not affect the original array structure.

const list = [1, 2, 3];

const clone = [...list];

console.log(clone); // [1, 2, 3]

Spread

The spread operator (...) expands arrays into a new array. This is commonly used to merge lists.

const a = [1, 2];
const b = [3, 4];

const combined = [...a, ...b];

console.log(combined); // [1, 2, 3, 4]

Reverse

Reverses the order of items in an array. This operation mutates the original array.

const list = [1, 2, 3, 4];

list.reverse();

console.log(list); // [4, 3, 2, 1]

Dedupe

Removes duplicate values from an array by converting it to a Set and back to an array.

const list = [1, 2, 2, 3, 3, 3];

const deduped = [...new Set(list)];

console.log(deduped); // [1, 2, 3]

Map

Iterate Map

Iterates over the entries of a Map, providing access to both keys and values.

const map = new Map([
    ["a", 1],
    ["b", 2]
]);

for (const [key, value] of map) {
    console.log(key, value);
}

Map Length

Returns the number of entries in a Map.

const map = new Map([
    ["a", 1],
    ["b", 2],
    ["c", 3]
]);

const length = map.size;

console.log(length); // 3

Object

Copy Shallow

Creates a shallow copy of an object. Properties are copied into a new object.

const obj = { a: 1, b: 2 };

const clone = { ...obj };

console.log(clone); // { a: 1, b: 2 }

Spread

The spread operator can be used with objects to merge properties into a new object.

const a = { x: 1, y: 2 };
const b = { y: 3, z: 4 };

const combined = { ...a, ...b };

console.log(combined);
// { x: 1, y: 3, z: 4 }

Class

Class Basics

A basic class example

class MyClass {
    constructor() {
        // initialization
    }

    doSomething() {
        console.log("I am doing something!");
    }
}

const myClass = new MyClass();
myClass.doSomething();

Advanced Class Features

An grab bag of advanced class features

class MyBaseClass {
    constructor(value) {
        this.value = value;
    }

    printValue() {
        console.log("My value is: " + this.value);
    }

    doSomething() {
        console.log("I am doing something!");
    }

    incrementValue() {
        this.value++;
        this.printValue();
        return this; // fluent style
    }
}

class MyChildClass extends MyBaseClass {
    constructor(value) {
        super(value);
    }

    doSomething() {
        console.log("I am overriding doing something!");
        super.doSomething();
    }
}

const myClass = new MyChildClass(5);

myClass.printValue();
myClass.doSomething();
myClass.incrementValue().incrementValue().incrementValue()

Bind Class Method

Class methods lose their this context when they are passed as callbacks. The bind() method creates a new function where this is permanently bound to the class instance.

class MyClass {
    constructor(value) {
        this.value = value;
        this.printValue = this.printValue.bind(this);
    }

    printValue() {
        console.log(this.value);
    }
}

const myClass = new MyClass(10);

setTimeout(myClass.printValue, 100);
// 10

Errors

Trigger an Error (Throw)

JavaScript errors can be created and thrown using throw. Thrown errors interrupt execution and can be handled using try and catch. This immediately stops execution and raises an error with the provided message.

throw new Error("Something went wrong");

Reacting to an Error (Catch)

Thrown errors stop execution unless they are caught.

try {
    throw new Error("Something went wrong");
} catch (err) {
    console.log(err.message);
}

Arrow Functions

Arrow functions (=>) can access variables defined outside the function. These variables are resolved from the surrounding scope where the function is created.

const factor = 3;

const multiply = value => {
    return value * factor;
};

multiply(4); // 12

File System

Index-based loops expose the iteration counter, while for...of loops iterate directly over values in an iterable. This is sometimes refered to as a C-style for loop or a counter-controlled loop. It is used when you need access to the index of the item in the list

Get All Files in a Folder (Recursively)

Recursively retrieves all files within a directory filtering results by file extension.

import fs from "fs/promises";
import path from "path";

const entries = await fs.readdir("./assets", {
    recursive: true,
    withFileTypes: true
});

const imageExtensions = [".png", ".jpg", ".jpeg", ".webp", ".gif"];

const imageFiles = entries
    .filter(entry => entry.isFile())
    .map(entry => path.join(entry.path, entry.name))
    .filter(file => imageExtensions.includes(path.extname(file)));

console.log(imageFiles);

A function wrapped version to implement as a util.

import fs from "fs/promises";
import path from "path";

/**
 * Recursively get all files in a directory, filtered by extension.
 *
 * @param {string} dir - Root directory to scan
 * @param {string[]} extensions - Allowed file extensions (e.g. ['.png', '.jpg'])
 * @returns {Promise<string[]>}
 */
export async function getFilesRecursive(dir, extensions = []) {
    const entries = await fs.readdir(dir, {
        recursive: true,
        withFileTypes: true
    });

    return entries
        .filter(entry => entry.isFile())
        .map(entry => path.join(entry.path, entry.name))
        .filter(file =>
            extensions.length === 0 ||
            extensions.includes(path.extname(file).toLowerCase())
        );
}

Check if File Exists

Node.js does not provide a simple built-in exists() function for files. The canonical way to check for existence is to attempt access and catch the error. This pattern works, but can feel heavy when used frequently.

In-Line

The minimal inline check:

import fs from "fs/promises";

let exists = true;

try {
    await fs.access(filePath);
} catch {
    exists = false;
}

Utility Function Version

Wrapping the pattern in a function makes it reusable, but the underlying mechanism is the same.

import fs from "fs/promises";

async function fileExists(filePath) {
    try {
        await fs.access(filePath);
        return true;
    } catch {
        return false;
    }
}

Path-Ok

This pattern comes up often enough that repeatedly writing try / catch can feel noisy and unintuitive for such a simple check. To avoid that friction, I wrote a small utility package that wraps this behavior.

import pathOk from "path-ok";

const exists = await pathOk(filePath);

Data Operations

Get By ID

Iterates over a list of objects and returns the item with a matching id.

function getById(list, id) {
    for (const item of list) {
        if (item.id === id) {
            return item;
        }
    }
    return null;
}

List to Map

Converts a list of objects with an id property into a map keyed by id.

function listToMap(list) {
    const map = {};

    for (const item of list) {
        map[item.id] = item;
    }

    return map;
}

JSON Operations

JavaScript includes built-in support for converting between JSON text and JavaScript values. Parsing reads JSON into memory, while serialization converts values back into JSON text. Pretty serialization formats the output for readability.

Parse JSON

Parsing JSON converts a JSON-formatted string into a JavaScript value. This is commonly used when reading JSON from files, APIs, or external input.

const jsonText = '{"name":"Alex","active":true,"count":3}';

const data = JSON.parse(jsonText);

console.log(data.name); // "Alex"

Serialize JSON

Serializing JSON converts a JavaScript value into a JSON string. This is used when writing data to files, sending data over a network, or storing structured information.

const data = {
    name: "Alex",
    active: true,
    count: 3
};

const jsonText = JSON.stringify(data);

console.log(jsonText);
// {"name":"Alex","active":true,"count":3}

Pretty Serialize JSON

Pretty serialization formats JSON output with indentation and line breaks. This improves readability and is commonly used for configuration files, logs, and debugging.

const data = {
    name: "Alex",
    active: true,
    count: 3
};

const prettyJson = JSON.stringify(data, null, 2);

console.log(prettyJson);
/*
{
    "name": "Alex",
    "active": true,
    "count": 3
}
*/

Provider