JavaScript Cheatsheet

Modules

Use this JavaScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

ES Modules (ESM)

ES Modules are the standard module system (import/export), supported natively in browsers and Node.js (.mjs or "type": "module" in package.json). Modules are strict mode by default, evaluated once, and statically analyzed.

Named Exports

// math.js
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
export class Vector { /* ... */ }

// Batch export
const x = 1;
const y = 2;
export { x, y };

// Rename on export
export { add as sum, subtract as diff };

Default Export

// Only one default per file
export default function greet(name) {
  return `Hello, ${name}!`;
}

// Or:
const greet = name => `Hello, ${name}!`;
export default greet;

// Class default
export default class User { /* ... */ }

Named Imports

// Import specific exports
import { add, PI } from "./math.js";
add(1, 2); // 3

// Rename on import
import { add as sum, subtract as diff } from "./math.js";

// Import all as namespace
import * as math from "./math.js";
math.add(1, 2); // 3
math.PI;        // 3.14159

Default Import

import greet from "./greet.js";    // any name, no braces
greet("Alice"); // "Hello, Alice!"

// Combine default + named
import greet, { helper, CONSTANT } from "./module.js";

Re-Exporting

// Re-export named
export { add, subtract } from "./math.js";
export { default as greet } from "./greet.js";

// Re-export all
export * from "./math.js";
export * as math from "./math.js"; // namespace re-export

// Rename during re-export
export { add as sum } from "./math.js";

Dynamic Import

// import() returns a Promise — for lazy loading or conditional imports
const math = await import("./math.js");
math.add(1, 2);

// Named exports
const { add, PI } = await import("./math.js");

// Default export
const { default: greet } = await import("./greet.js");

// Conditional
if (process.env.NODE_ENV === "development") {
  const { devTools } = await import("./dev-tools.js");
  devTools.enable();
}

// In non-async context
import("./module.js")
  .then(module => module.doSomething())
  .catch(console.error);

CommonJS (CJS — Node.js)

CommonJS is the older Node.js module system. Not natively supported in browsers.

// Exporting
module.exports = { add, subtract };      // export object
module.exports = function greet() {};    // export single value
exports.add = function() {};             // named export shorthand
// Note: mixing module.exports and exports breaks exports

// Importing
const math = require("./math");          // relative path
const math2 = require("./math.js");     // extension optional
const path = require("path");            // built-in module
const express = require("express");      // npm package

// Destructure on require
const { add, subtract } = require("./math");

// Dynamic require
const name = "math";
const mod = require(`./${name}`);       // runtime path resolution

CJS vs ESM Key Differences

FeatureESMCJS
Syntaximport/exportrequire/module.exports
Load timestatic (compile-time)dynamic (runtime)
Asyncyes (top-level await)no
this at top levelundefinedmodule.exports
__filename / __dirnamenot available*available
File extension.mjs or .js (in ESM package).cjs or .js
Tree-shakeableyesno

*In ESM: import.meta.url, import.meta.dirname (Node 20.11+)

// ESM equivalents of __filename / __dirname
import { fileURLToPath } from "url";
import { dirname } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Node 20.11+:
const __dirname = import.meta.dirname;

import.meta

import.meta.url       // URL of current module: "file:///path/to/file.js"
import.meta.dirname   // directory (Node 20.11+)
import.meta.filename  // file path (Node 20.11+)
import.meta.env       // environment vars in Vite/bundlers
import.meta.env.DEV   // true in development (Vite)
import.meta.resolve("lodash") // resolve module specifier to URL

Module Patterns

Barrel File (index.js)

// src/utils/index.js — re-export everything for clean imports
export { formatDate, parseDate } from "./dates.js";
export { sum, average, round } from "./math.js";
export { capitalize, truncate } from "./strings.js";

// Consumer
import { formatDate, sum } from "./utils/index.js";
// or:
import { formatDate, sum } from "./utils"; // bundlers resolve index

Module with Private State

// counter.js — encapsulate state
let count = 0;          // module-private

export function increment() { return ++count; }
export function decrement() { return --count; }
export function reset()     { count = 0; }
export const getCount = () => count;

Conditional Module (platform detection)

// detect.js
export const isBrowser = typeof window !== "undefined";
export const isNode = typeof process !== "undefined" && process.versions?.node;

// Lazy platform module
const storage = isBrowser
  ? await import("./browser-storage.js")
  : await import("./node-storage.js");

Tree Shaking

Tree shaking removes unused exports at bundle time. Only works with ESM static imports.

// GOOD — bundler can tree-shake (static analysis)
import { add } from "./math.js"; // subtract not imported → excluded from bundle

// BAD for tree-shaking — dynamic (bundler can't know what's used)
const { add } = require("./math"); // CJS — whole module included
const fn = await import(dynamicPath); // dynamic path — can't analyze

Circular Dependencies

// a.js
import { b } from "./b.js";
export const a = "a";
console.log(b); // may be undefined during init — circular

// b.js
import { a } from "./a.js";
export const b = "b";
console.log(a); // may be undefined during init — circular

// Solution: move shared code to a third module or use functions

Loading in HTML (Browser)

<!-- ES Module — deferred by default, not executed until DOM ready -->
<script type="module" src="app.js"></script>

<!-- Inline module -->
<script type="module">
  import { greet } from "./greet.js";
  greet("World");
</script>

<!-- Import map — browser-native bare specifier resolution -->
<script type="importmap">
{
  "imports": {
    "lodash": "https://cdn.jsdelivr.net/npm/lodash-es/lodash.js",
    "utils/": "./src/utils/"
  }
}
</script>
<script type="module">
  import { debounce } from "lodash";       // resolves via importmap
  import { formatDate } from "utils/dates.js";
</script>