|$ curl https://forge-ai.dev/api/markdown?path=docs/js
$cat docs/javascript-—-getting-started.md
updated Recently·42 min read·published

JavaScript — Getting Started

JavaScriptBeginner to Advanced
Introduction

JavaScript (often abbreviated as JS) is a high-level, interpreted programming language that conforms to the ECMAScript specification. It is one of the three core technologies of the World Wide Web, alongside HTML and CSS, and is the only programming language natively supported by all modern web browsers.

JavaScript enables interactive web pages and is an essential part of web applications. The majority of websites use it for client-side page behavior, and all major web browsers have a dedicated JavaScript engine to execute it. Beyond the browser, JavaScript powers servers (Node.js), desktop applications (Electron), mobile apps (React Native), and even embedded systems.

Unlike other languages, JavaScript runs in an event-driven, single-threaded environment with asynchronous capabilities via the event loop. This design makes it uniquely suited for UI-intensive applications while requiring careful thinking about concurrency patterns.

hello.js
JavaScript
1// Your first JavaScript program
2console.log("Hello, World!");
3
4// JavaScript runs in the browser's console
5// or in any JavaScript runtime environment
6
7// Interactive example — try in your browser console:
8const greeting = "Hello, World!";
9console.log(greeting);
10// → Hello, World!
preview
History & Evolution

JavaScript was created by Brendan Eich at Netscape in 1995 in just ten days. Originally called Mocha, then LiveScript, it was renamed JavaScript as a marketing ploy to capitalize on Java's popularity. Despite the name, JavaScript and Java are entirely different languages with different syntax, semantics, and use cases.

The language was standardized as ECMAScript in 1997. After a period of stagnation (ES4 was abandoned), the ecosystem revitalized with ES5 (2009), which introduced strict mode, JSON support, and array methods. The modern era began with ES6/ES2015, which brought classes, modules, arrow functions, promises, destructuring, and many other features.

Since ES2015, TC39 (the standards committee) has followed a yearly release cycle. Key milestones include ES2017 (async/await), ES2018 (rest/spread for objects), ES2020 (optional chaining, nullish coalescing), ES2021 (logical assignment operators), ES2023 (array find from last), and ES2024 (groupBy, Promise.withResolvers).

VersionYearKey Features
ES31999Regular expressions, try/catch, switch
ES52009Strict mode, JSON, Array methods (forEach, map, filter), getters/setters
ES6/20152015let/const, arrow functions, classes, modules, promises, destructuring, template literals
ES20162016Array.includes, exponentiation operator (**)
ES20172017async/await, Object.entries/values, string padding
ES20182018Rest/spread for objects, Promise.finally, async iteration
ES20202020Optional chaining (?.), nullish coalescing (??), globalThis, BigInt
ES20212021Logical assignment (&&=, ||=, ??=), String.replaceAll, Promise.any
ES20232023Array.findLast, toSpliced/toSorted/toReversed, Hashbang Grammar
ES20242024Promise.withResolvers, Object.groupBy, ArrayBuffer transfer, RegExp v flag

info

You do not need to memorize the ECMAScript version history. Modern JavaScript compilers like Babel and bundlers like Vite transpile modern JS to older syntax for browser compatibility. Write modern JS and let the tooling handle the rest.
Development Setup

To start writing JavaScript, you only need a web browser and a text editor. Every modern browser includes a developer console for running JavaScript interactively. For more serious development, set up Node.js and a code editor.

Browser Console

Press F12 or Ctrl+Shift+I (Windows) / Cmd+Option+I (Mac) to open DevTools. The Console tab lets you execute JavaScript in the context of any web page.

console.js
JavaScript
1// Try these in your browser console:
2console.log("Hello from the console!");
3
4// Inspect the current page
5console.dir(document);
6console.log(window.innerWidth, window.innerHeight);
7
8// Benchmark performance
9console.time("loop");
10let sum = 0;
11for (let i = 0; i < 1000000; i++) sum += i;
12console.timeEnd("loop");
13
14// Interactive debugging
15const data = { name: "Alice", age: 30 };
16console.table(data);

Node.js Runtime

Node.js is a JavaScript runtime built on Chrome's V8 engine. It allows you to run JavaScript on the server or command line. Install it from nodejs.org and verify with node -v.

terminal.sh
Bash
1# Install Node.js (via nvm — recommended)
2nvm install --lts
3node -v
4# → v22.x.x
5
6# Run a JavaScript file
7node hello.js
8
9# Start a REPL (Read-Eval-Print Loop)
10node
11
12# Execute inline code
13node -e "console.log('Hello from Node!')"

Essential Dev Tools

ToolPurpose
VS CodePopular code editor with built-in JS support, debugger, and extensions
Chrome DevToolsDebugging, profiling, network inspection, console for live JS
Node.jsServer-side runtime with npm package manager
ESLintLinter that catches errors and enforces code style
PrettierAutomatic code formatter for consistent style
ViteFast development server and build tool for modern JS projects

best practice

Always use a linter (ESLint) and formatter (Prettier) from the start. They catch subtle bugs, enforce consistency, and make code reviews more productive. Configure them with a .eslintrc and .prettierrc in your project root.
Variables

Variables are used to store data values. JavaScript provides three keywords for declaring variables: var, let, and const. Modern JavaScript strongly favors const by default and let when reassignment is needed.

KeywordScopeHoistingReassignmentRedeclarationUse Case
varFunction scopeHoisted (initialized as undefined)Legacy code only — avoid in modern JS
letBlock scopeHoisted (not initialized — TDZ)When you need to reassign the variable
constBlock scopeHoisted (not initialized — TDZ)Default choice — prevents reassignment
variables.js
JavaScript
1// const — cannot be reassigned (use by default)
2const name = "Alice";
3name = "Bob"; // TypeError: Assignment to constant variable
4
5// const with objects — the reference is constant, not the value
6const user = { name: "Alice" };
7user.name = "Bob"; // ✓ Works — mutating the object is allowed
8user = {}; // TypeError: Assignment to constant variable
9
10// let — can be reassigned, block-scoped
11let count = 0;
12count = 1; // ✓ OK
13let count = 2; // SyntaxError: redeclaration
14
15// var — function-scoped, hoisted, avoid in modern code
16var x = 10;
17if (true) {
18 var x = 20; // Same variable! No block scope
19}
20console.log(x); // 20 (var leaks out of the block)
21
22// Temporal Dead Zone (TDZ)
23console.log(y); // ReferenceError: Cannot access before initialization
24let y = 5;

warning

The Temporal Dead Zone (TDZ) applies to let and const but not var. Accessing a variable before its declaration throws a ReferenceError. This is a deliberate design improvement over var's behavior, which silently returns undefined.
Data Types

JavaScript has two categories of data types: primitive types and reference types. Primitives are immutable values stored directly in the variable. Reference types store a reference to a value in memory.

Primitive Types

TypeExampletypeof ResultNotes
string"hello""string"Single, double, or backtick quotes
number42, 3.14, NaN"number"64-bit floating point (no integer type)
booleantrue, false"boolean"Logical true/false
undefinedundefined"undefined"Variable declared but not assigned
nullnull"object"Intentional absence of value (typeof bug)
symbolSymbol("id")"symbol"Unique, immutable identifier (ES6)
bigint9007199254740991n"bigint"Arbitrary precision integers (ES2020)

Reference Types

Reference types store a memory address pointing to the actual data. When you assign or compare reference types, you are working with references, not the values themselves.

reference-types.js
JavaScript
1// Object — collection of key-value pairs
2const person = {
3 name: "Alice",
4 age: 30,
5 greet() { console.log(`Hi, I'm ${this.name}`); }
6};
7
8// Array — ordered list
9const fruits = ["apple", "banana", "cherry"];
10fruits.push("date");
11console.log(fruits[0]); // "apple"
12
13// Function — callable value
14function add(a, b) { return a + b; }
15
16// Date
17const now = new Date();
18console.log(now.toISOString()); // "2026-07-07T..."
19
20// Map — key-value with any key types
21const map = new Map();
22map.set("key", "value");
23
24// Set — unique values
25const set = new Set([1, 2, 3, 3, 3]);
26console.log(set.size); // 3
27
28// typeof pitfalls
29console.log(typeof null); // "object" (legacy bug)
30console.log(typeof []); // "object"
31console.log(typeof add); // "function"
32console.log(Array.isArray([])); // true

info

Use Array.isArray() to check for arrays, not typeof. Use === null to check for null. The typeof null === "object" is a well-known bug from the first version of JavaScript that cannot be fixed for backward compatibility.
Operators

JavaScript provides a rich set of operators for arithmetic, comparison, logical operations, and more. Understanding the nuances of each operator is essential for writing correct code.

Arithmetic Operators

arithmetic.js
JavaScript
1// Basic arithmetic
2console.log(5 + 3); // 8
3console.log(5 - 3); // 2
4console.log(5 * 3); // 15
5console.log(5 / 3); // 1.666...
6console.log(5 % 3); // 2 (remainder)
7console.log(2 ** 4); // 16 (exponentiation, ES2016)
8
9// Increment / decrement
10let count = 0;
11count++; // Post-increment: returns 0, then sets to 1
12++count; // Pre-increment: sets to 2, returns 2
13count--; // Post-decrement
14
15// Type coercion in arithmetic
16console.log(1 + "2"); // "12" (string concatenation)
17console.log("5" - 2); // 3 (coerces string to number)
18console.log("5" * "2"); // 10
19console.log(+"5"); // 5 (unary plus converts to number)
20console.log("hello" - 1); // NaN (not a number)
21
22// Operator precedence
23console.log(2 + 3 * 4); // 14 (multiplication first)
24console.log((2 + 3) * 4); // 20 (parentheses override)

Comparison Operators

comparison.js
JavaScript
1// Strict equality (recommended) — compares value AND type
2console.log(5 === 5); // true
3console.log(5 === "5"); // false (number !== string)
4
5// Loose equality — coerces types before comparing (avoid)
6console.log(5 == "5"); // true (coerces string to number)
7console.log(0 == false); // true
8console.log("" == false); // true
9
10// Strict inequality
11console.log(5 !== "5"); // true
12
13// Relational operators
14console.log(5 > 3); // true
15console.log(5 <= 5); // true
16
17// Loose equality quirks (reasons to avoid ==)
18console.log(null == undefined); // true
19console.log(null === undefined); // false
20console.log([] == false); // true
21console.log([1] == 1); // true
22
23// Object comparison — references are compared, not values
24console.log({} == {}); // false (different references)
25console.log([] == []); // false

Logical, Ternary & Modern Operators

logical.js
JavaScript
1// Logical operators
2console.log(true && false); // false (AND)
3console.log(true || false); // true (OR)
4console.log(!true); // false (NOT)
5
6// Short-circuit evaluation
7const user = null;
8const name = user && user.name; // null (short-circuits on falsy)
9const fallback = user || "guest"; // "guest"
10const sure = user ?? "guest"; // "guest" (nullish coalescing)
11
12// Nullish coalescing (??) — only for null/undefined, not other falsy
13const count = 0;
14console.log(count || 10); // 10 (0 is falsy)
15console.log(count ?? 10); // 0 (0 is not null/undefined)
16
17// Ternary operator
18const age = 20;
19const status = age >= 18 ? "adult" : "minor";
20
21// Optional chaining (?.) — safe property access
22const data = { user: { address: null } };
23console.log(data.user?.address?.city); // undefined (no error)
24console.log(data.user?.getName?.()); // undefined (optional method call)
25
26// Logical assignment operators (ES2021)
27let x = 0;
28x ||= 10; // x = x || 10 → 10 (assigns if falsy)
29let y = 1;
30y &&= 10; // y = y && 10 → 10 (assigns if truthy)
31let z = null;
32z ??= 10; // z = z ?? 10 → 10 (assigns if null/undefined)

warning

The || operator treats all falsy values (0, "", false, null, undefined, NaN) as false. The ?? operator only treats null and undefined as false. Use ?? for default values when 0 or "" are valid inputs.
Control Flow

Control flow statements determine the order in which code executes. JavaScript supports conditionals, loops, and branching constructs common to most programming languages.

Conditionals — if/else

conditionals.js
JavaScript
1const score = 85;
2
3if (score >= 90) {
4 console.log("A");
5} else if (score >= 80) {
6 console.log("B");
7} else if (score >= 70) {
8 console.log("C");
9} else {
10 console.log("Failing grade");
11}
12
13// Truthiness — values that coerce to true/false
14if ("hello") console.log("truthy"); // non-empty strings
15if (42) console.log("truthy"); // non-zero numbers
16if ([]) console.log("truthy"); // empty arrays (yes!)
17if ({}) console.log("truthy"); // empty objects (yes!)
18if (0) console.log("falsy"); // never runs
19if ("") console.log("falsy"); // never runs
20if (null) console.log("falsy"); // never runs
21if (undefined) console.log("falsy"); // never runs
22if (NaN) console.log("falsy"); // never runs
23
24// Early return pattern (avoids nested ifs)
25function divide(a, b) {
26 if (b === 0) return "Cannot divide by zero";
27 if (typeof a !== "number") return "Invalid input";
28 return a / b;
29}

Switch Statement

switch.js
JavaScript
1const day = "Wednesday";
2
3switch (day) {
4 case "Monday":
5 console.log("Start of work week");
6 break;
7 case "Wednesday":
8 case "Thursday":
9 console.log("Midweek");
10 break;
11 case "Friday":
12 console.log("TGIF");
13 break;
14 default:
15 console.log("Weekend");
16}
17
18// Switch with return (cleaner in functions)
19function getDayType(day) {
20 switch (day) {
21 case "Saturday":
22 case "Sunday":
23 return "weekend";
24 default:
25 return "weekday";
26 }
27}
28
29// Better alternative: object lookup
30const dayTypes = {
31 Monday: "weekday",
32 Tuesday: "weekday",
33 Saturday: "weekend",
34 Sunday: "weekend",
35};
36console.log(dayTypes["Monday"] ?? "invalid day");

Loops

loops.js
JavaScript
1// for loop
2for (let i = 0; i < 5; i++) {
3 console.log(i); // 0, 1, 2, 3, 4
4}
5
6// while loop
7let i = 0;
8while (i < 5) {
9 console.log(i);
10 i++;
11}
12
13// do...while (runs at least once)
14let j = 0;
15do {
16 console.log(j);
17 j++;
18} while (j < 5);
19
20// for...of (iterables — arrays, strings, maps, sets)
21const fruits = ["apple", "banana", "cherry"];
22for (const fruit of fruits) {
23 console.log(fruit);
24}
25
26// for...in (object keys — avoid for arrays)
27const person = { name: "Alice", age: 30 };
28for (const key in person) {
29 console.log(`${key}: ${person[key]}`);
30}
31
32// Array methods as loop alternatives
33fruits.forEach((fruit, index) => {
34 console.log(`${index}: ${fruit}`);
35});
36
37const doubled = fruits.map(f => f.toUpperCase());
38const hasApple = fruits.some(f => f === "apple");
39const allFruits = fruits.every(f => f.length > 1);
🔥

pro tip

Prefer for...of over for...in for arrays. The for...in loop iterates over enumerable properties, which includes inherited properties and can yield unexpected results. Use for...of for arrays, strings, Maps, and Sets.
Functions

Functions are the fundamental building blocks of JavaScript. They are first-class objects, meaning they can be assigned to variables, passed as arguments, and returned from other functions.

Function Declaration vs Expression vs Arrow

TypeHoistedthis Bindingarguments ObjectUse Case
Declaration Fully hoistedDynamic (call-site)Named functions, recursion, hoisting needed
Expression Not hoistedDynamic (call-site)Callbacks, IIFEs, conditional definitions
Arrow Not hoistedLexical (inherits from scope) (use rest params)Short callbacks, preserving this context
functions.js
JavaScript
1// Function declaration (hoisted — can be called before definition)
2console.log(add(2, 3)); // 5
3function add(a, b) {
4 return a + b;
5}
6
7// Function expression (not hoisted)
8const subtract = function (a, b) {
9 return a - b;
10};
11console.log(subtract(5, 3)); // 2
12
13// Arrow function (not hoisted, implicit return for single expressions)
14const multiply = (a, b) => a * b;
15console.log(multiply(4, 3)); // 12
16
17// Arrow with block body (explicit return needed)
18const divide = (a, b) => {
19 if (b === 0) throw new Error("Division by zero");
20 return a / b;
21};
22
23// Parameters and default values
24function greet(name = "Guest", greeting = "Hello") {
25 return `${greeting}, ${name}!`;
26}
27console.log(greet()); // "Hello, Guest!"
28console.log(greet("Alice")); // "Hello, Alice!"
29console.log(greet("Bob", "Hi")); // "Hi, Bob!"
30
31// Rest parameters (...)
32function sum(...numbers) {
33 return numbers.reduce((acc, n) => acc + n, 0);
34}
35console.log(sum(1, 2, 3, 4)); // 10
36
37// First-class functions
38const operators = {
39 add: (a, b) => a + b,
40 subtract: (a, b) => a - b,
41 multiply: (a, b) => a * b,
42};
43console.log(operators.add(5, 3)); // 8
44
45// Higher-order function (takes or returns a function)
46function createMultiplier(factor) {
47 return (n) => n * factor;
48}
49const double = createMultiplier(2);
50console.log(double(5)); // 10
51
52// Immediately Invoked Function Expression (IIFE)
53(function () {
54 const secret = "this is private";
55 console.log(secret);
56})();

best practice

Use function declarations for named utility functions (they are hoisted, making code more readable). Use arrow functions for short callbacks and when you need lexical this. Avoid arrow functions as methods in objects or classes — they do not have their own this binding.
Scope & Closures

Scope determines where variables are accessible in your code. JavaScript has global, function, and block scope. Closures are functions that retain access to their lexical scope even when executed outside that scope.

Scope Types

scope.js
JavaScript
1// Global scope — accessible everywhere
2const globalVar = "I'm global";
3
4function demo() {
5 // Function scope — accessible within this function
6 var functionScoped = "I'm function-scoped";
7 let blockScoped = "I'm block-scoped";
8
9 if (true) {
10 // Block scope — let and const are block-scoped
11 let blockVar = "Only in this block";
12 const alsoBlock = "Also only in this block";
13 var notBlockScoped = "I escape the block!"; // var ignores blocks
14 }
15
16 console.log(notBlockScoped); // "I escape the block!"
17 // console.log(blockVar); // ReferenceError
18}
19
20// Lexical scope — inner functions can access outer scopes
21const outer = "outer";
22function parent() {
23 const middle = "middle";
24 function child() {
25 const inner = "inner";
26 console.log(outer); // "outer"
27 console.log(middle); // "middle"
28 console.log(inner); // "inner"
29 }
30 child();
31}
32parent();

Closures

A closure is created when a function retains access to its enclosing scope's variables, even after the outer function has returned. This is one of JavaScript's most powerful features.

closures.js
JavaScript
1// Basic closure — inner function keeps access to outer vars
2function createCounter() {
3 let count = 0; // "closed over" variable
4 return function () {
5 count++;
6 return count;
7 };
8}
9
10const counter = createCounter();
11console.log(counter()); // 1
12console.log(counter()); // 2
13console.log(counter()); // 3
14
15// Each call to createCounter creates a new closure
16const counterA = createCounter();
17const counterB = createCounter();
18console.log(counterA()); // 1
19console.log(counterB()); // 1 (independent)
20
21// Practical: data privacy (module pattern)
22function createBankAccount(initialBalance) {
23 let balance = initialBalance;
24 return {
25 deposit(amount) {
26 if (amount > 0) balance += amount;
27 return balance;
28 },
29 withdraw(amount) {
30 if (amount > 0 && balance >= amount) {
31 balance -= amount;
32 return balance;
33 }
34 return "Insufficient funds";
35 },
36 getBalance() {
37 return balance;
38 },
39 };
40}
41
42const account = createBankAccount(100);
43console.log(account.getBalance()); // 100
44account.deposit(50);
45console.log(account.getBalance()); // 150
46// console.log(account.balance); // undefined (private!)
47
48// Practical: function factories
49function createGreeting(greeting) {
50 return (name) => `${greeting}, ${name}!`;
51}
52
53const sayHello = createGreeting("Hello");
54const sayHi = createGreeting("Hi");
55console.log(sayHello("Alice")); // "Hello, Alice!"
56console.log(sayHi("Bob")); // "Hi, Bob!"
🔥

pro tip

Closures are the foundation of the module pattern, function factories, currying, and many functional programming techniques in JavaScript. Every time you pass a callback to setTimeout, fetch, or addEventListener, you are using closures.
Modern JavaScript Features

ECMAScript 2015 (ES6) and subsequent releases introduced powerful features that make JavaScript code more concise, readable, and less error-prone. These features are now universally supported in modern environments.

Destructuring

destructuring.js
JavaScript
1// Array destructuring
2const colors = ["red", "green", "blue"];
3const [first, second, third] = colors;
4console.log(first); // "red"
5console.log(second); // "green"
6
7// Skip elements with commas
8const [, , last] = colors;
9console.log(last); // "blue"
10
11// Default values
12const [a = 10, b = 20] = [5];
13console.log(a); // 5
14console.log(b); // 20 (default used)
15
16// Swapping variables
17let x = 1, y = 2;
18[x, y] = [y, x];
19
20// Object destructuring
21const person = { name: "Alice", age: 30, city: "NYC" };
22const { name, age } = person;
23console.log(name); // "Alice"
24
25// Renaming and defaults
26const { name: personName, country = "Unknown" } = person;
27console.log(personName); // "Alice"
28console.log(country); // "Unknown"
29
30// Nested destructuring
31const data = { user: { id: 1, profile: { displayName: "Alice" } } };
32const { user: { profile: { displayName } } } = data;
33console.log(displayName); // "Alice"
34
35// Destructuring parameters
36function printUser({ name, age, city = "Unknown" }) {
37 console.log(`${name} (${age}) - ${city}`);
38}
39printUser(person); // "Alice (30) - NYC"

Spread & Rest

spread-rest.js
JavaScript
1// Spread — expands an iterable into elements
2const arr1 = [1, 2, 3];
3const arr2 = [4, 5, 6];
4const combined = [...arr1, ...arr2];
5console.log(combined); // [1, 2, 3, 4, 5, 6]
6
7// Copy an array (shallow)
8const copy = [...arr1];
9
10// Spread object properties
11const base = { x: 1, y: 2 };
12const extended = { ...base, z: 3 };
13console.log(extended); // { x: 1, y: 2, z: 3 }
14
15// Override properties (later overrides earlier)
16const user = { name: "Alice", role: "user" };
17const admin = { ...user, role: "admin" };
18console.log(admin); // { name: "Alice", role: "admin" }
19
20// Shallow copy of object
21const cloned = { ...user };
22
23// Rest parameters — collects remaining args into array
24function logAll(first, ...rest) {
25 console.log(first); // first argument
26 console.log(rest); // array of remaining arguments
27}
28logAll("a", "b", "c", "d"); // first="a", rest=["b","c","d"]
29
30// Rest in destructuring
31const [head, ...tail] = [1, 2, 3, 4];
32console.log(head); // 1
33console.log(tail); // [2, 3, 4]
34
35const { name: n, ...restProps } = { name: "Alice", age: 30, city: "NYC" };
36console.log(n); // "Alice"
37console.log(restProps); // { age: 30, city: "NYC" }

Template Literals

template-literals.js
JavaScript
1// String interpolation
2const name = "Alice";
3const age = 30;
4console.log(`My name is ${name} and I am ${age} years old.`);
5// "My name is Alice and I am 30 years old."
6
7// Expressions inside templates
8console.log(`2 + 2 = ${2 + 2}`); // "2 + 2 = 4"
9
10// Multi-line strings (no more \n concatenation)
11const html = `
12 <div>
13 <h1>${name}</h1>
14 <p>Age: ${age}</p>
15 </div>
16`;
17
18// Tagged templates
19function highlight(strings, ...values) {
20 return strings.reduce((result, str, i) => {
21 const val = values[i] ? `<mark>${values[i]}</mark>` : "";
22 return result + str + val;
23 }, "");
24}
25const highlighted = highlight`User ${name} is ${age} years old.`;
26console.log(highlighted);
27// "User <mark>Alice</mark> is <mark>30</mark> years old."

Optional Chaining & Nullish Coalescing

optional-chaining.js
JavaScript
1// Before optional chaining — verbose and error-prone
2if (data && data.user && data.user.profile) {
3 console.log(data.user.profile.name);
4}
5
6// With optional chaining — clean and safe
7console.log(data?.user?.profile?.name); // undefined (no error)
8
9// Optional method call
10const result = obj?.method?.();
11// If obj is null/undefined, result is undefined
12// If obj.method doesn't exist, result is undefined
13// Otherwise, calls the method
14
15// Optional property access with dynamic keys
16const key = "address";
17console.log(data?.user?.[key]?.city);
18
19// Nullish coalescing — provides default for null/undefined only
20const timeout = config.timeout ?? 3000;
21// Uses 3000 only if config.timeout is null or undefined
22// If config.timeout is 0, it uses 0 (unlike ||)
23
24// Combining optional chaining with nullish coalescing
25const userName = data?.user?.name ?? "Anonymous";
26console.log(userName); // "Anonymous" if any part is null/undefined
27
28// Practical: safe array access
29const firstItem = arr?.[0] ?? "default";

best practice

Use optional chaining (?.) whenever you access deeply nested properties that might be null or undefined. Pair it with nullish coalescing (??) for safe defaults. Together they eliminate the need for most manual null-checking boilerplate.
Best Practices

Strict Mode

Strict mode eliminates silent errors, fixes common JavaScript pitfalls, and enables future language features. Always enable it by adding "use strict" at the top of your scripts or modules. ES modules are strict by default.

strict-mode.js
JavaScript
1"use strict";
2
3// Silent errors become thrown errors
4// undeclaredVar = 42; // ReferenceError (without strict: creates global)
5// delete Object.prototype; // TypeError (without strict: silently fails)
6
7// this is undefined in functions instead of the global object
8function showThis() {
9 console.log(this); // undefined (in strict mode)
10}
11showThis();

Naming Conventions

ConventionExampleUse For
camelCaseuserName, fetchDataVariables, functions, methods
PascalCaseUserProfile, ApiClientClasses, constructors, components
UPPER_SNAKEMAX_RETRIES, API_KEYConstants, environment variables
_private_internalFn, _cachePrivate/internal (convention only)
$prefix$el, $containerDOM references (jQuery convention)

Essential Guidelines

Always use === and !== instead of == and != — avoid type coercion surprises
Prefer const over let, and let over var — const prevents accidental reassignment
Avoid global variables — they pollute the global namespace and cause naming conflicts
Use strict mode — either 'use strict' or ES modules (which are strict by default)
Handle errors with try/catch and always validate external input
Write pure functions when possible — same input always produces same output, no side effects
Use early returns to avoid deep nesting — flatten your code
Avoid modifying function parameters — treat them as read-only
Name functions and variables descriptively — code is read more often than written
Keep functions small and single-purpose — each function should do one thing well
Use meaningful error messages — they are the first line of debugging
Comment the why, not the what — good code is self-documenting for the 'what'

Common Pitfalls

✗ Implicit Globals

function setVal() { x = 10; } // x becomes global!

Always declare variables with const/let. Without strict mode, assignment to an undeclared variable creates a global.

✗ Loose Equality Surprises

console.log(false == "0"); // true (what?!)

Always use === to avoid JavaScript's complex type coercion rules.

✗ Floating Point Precision

console.log(0.1 + 0.2 === 0.3); // false

Use a tolerance (Math.abs(a - b) < Number.EPSILON) or a decimal library for precise financial calculations.

✗ Async/Await Without Error Handling

async function load() { const data = await fetch(url); } // unhandled rejection

Always wrap await calls in try/catch, or attach .catch() to promises. Unhandled rejections crash Node.js processes.

best practice

The single most impactful habit you can adopt: use "use strict" (or ES modules), prefer const, avoid globals, and always use ===. These four rules eliminate entire categories of JavaScript bugs.
$Blueprint — Engineering Documentation·Section ID: JS-01·Revision: 1.0