JavaScript Patterns & Collections

Array Methods

Essential functional array methods
const hosts = [
    { name: "sw01", vlan: 10, active: true },
    { name: "sw02", vlan: 20, active: false },
    { name: "fw01", vlan: 10, active: true },
    { name: "sw03", vlan: 20, active: true },
];

// map — transform each element
const names = hosts.map(h => h.name);
// ["sw01", "sw02", "fw01", "sw03"]

// filter — keep matching elements
const active = hosts.filter(h => h.active);

// find — first match
const firewall = hosts.find(h => h.name.startsWith("fw"));

// some / every
const hasInactive = hosts.some(h => !h.active);    // true
const allActive = hosts.every(h => h.active);       // false

// reduce — accumulate
const byVlan = hosts.reduce((acc, h) => {
    (acc[h.vlan] ??= []).push(h);
    return acc;
}, {});
// { 10: [{sw01}, {fw01}], 20: [{sw02}, {sw03}] }

// flatMap — map + flatten
const ports = hosts.flatMap(h => h.ports ?? []);

// sort (mutates!) — use toSorted() to avoid mutation
const sorted = [...hosts].sort((a, b) => a.name.localeCompare(b.name));

Object Methods

Keys, values, entries, fromEntries
const config = { host: "localhost", port: 8080, debug: true };

Object.keys(config);     // ["host", "port", "debug"]
Object.values(config);   // ["localhost", 8080, true]
Object.entries(config);  // [["host","localhost"], ["port",8080], ["debug",true]]

// Transform object entries
const upper = Object.fromEntries(
    Object.entries(config).map(([k, v]) => [k.toUpperCase(), v])
);
// { HOST: "localhost", PORT: 8080, DEBUG: true }

// Merge objects
const merged = { ...defaults, ...overrides };
const merged2 = Object.assign({}, defaults, overrides);

Map and Set

Modern collections
// Map — any key type, ordered, iterable
const cache = new Map();
cache.set("sw01", { ip: "10.50.1.10" });
cache.get("sw01");            // { ip: "10.50.1.10" }
cache.has("sw01");            // true
cache.delete("sw01");
cache.size;                   // 0

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

// Set — unique values
const seen = new Set();
seen.add("10.50.1.1");
seen.add("10.50.1.1");  // no-op
seen.size;               // 1
seen.has("10.50.1.1");  // true

// Deduplicate an array
const unique = [...new Set([1, 2, 2, 3, 3, 3])];
// [1, 2, 3]

Map preserves insertion order and accepts any key type (objects, functions). Plain objects coerce keys to strings.

Error Classes

Custom error types
class AppError extends Error {
    constructor(message, statusCode) {
        super(message);
        this.name = "AppError";
        this.statusCode = statusCode;
    }
}

class NotFoundError extends AppError {
    constructor(resource) {
        super(`${resource} not found`, 404);
        this.name = "NotFoundError";
    }
}

try {
    throw new NotFoundError("Host sw99");
} catch (err) {
    if (err instanceof NotFoundError) {
        console.log(err.statusCode);  // 404
    }
}

Generators

Lazy sequences with function*
function* range(start, end) {
    for (let i = start; i < end; i++) {
        yield i;
    }
}

for (const n of range(0, 5)) {
    console.log(n);  // 0, 1, 2, 3, 4
}

// Infinite sequence
function* fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

// Take first 10
const first10 = [];
for (const n of fibonacci()) {
    first10.push(n);
    if (first10.length >= 10) break;
}

Generators are lazy — values are produced one at a time. Combined with for…​of, they provide memory-efficient iteration over large or infinite sequences.

Proxy

Intercept object operations
const handler = {
    get(target, prop) {
        console.log(`accessing ${prop}`);
        return prop in target ? target[prop] : `unknown: ${prop}`;
    },
    set(target, prop, value) {
        if (prop === "port" && (value < 1 || value > 65535)) {
            throw new RangeError(`Invalid port: ${value}`);
        }
        target[prop] = value;
        return true;
    },
};

const config = new Proxy({}, handler);
config.port = 8080;    // OK
// config.port = 99999;  // RangeError

Proxies intercept property access, assignment, deletion, and more. Use them for validation, logging, and reactive programming patterns.