Skip to main content

JavaScript Fundamentals

JavaScript is a dynamically typed, interpreted language. Understanding its type system and how values behave is critical to writing bug-free code.

1. How JavaScript Works

Unlike compiled languages like Java or C++, JavaScript is interpreted at runtime. Modern engines like V8 (Chrome, Node.js) use Just-In-Time (JIT) compilation for performance.

The Process

  1. Parsing: Your code is parsed into an Abstract Syntax Tree (AST).
  2. Interpreter: The AST is converted to bytecode and executed immediately.
  3. JIT Compiler: Hot code paths are compiled to optimized machine code.
Key Takeaway: JavaScript is fast enough for most use cases thanks to JIT compilation.

2. Variables & Declarations

JavaScript has three ways to declare variables. Use const by default, let when you need to reassign, and avoid var.

const (Block-scoped, No Reassignment)

const PI = 3.14159;
PI = 3; // ❌ TypeError: Assignment to constant variable

// Note: Objects and arrays are still mutable!
const user = { name: 'Alice' };
user.name = 'Bob'; // ✅ This works
user = {};         // ❌ This fails

let (Block-scoped, Reassignable)

let count = 0;
count = 1; // ✅ Works fine

if (true) {
    let message = 'Hello';
}
console.log(message); // ❌ ReferenceError: message is not defined

var (Function-scoped, Hoisted) — Avoid!

console.log(x); // undefined (hoisted, but not initialized)
var x = 5;

// var ignores block scope
if (true) {
    var leaked = 'I escaped!';
}
console.log(leaked); // 'I escaped!' — This is a bug waiting to happen
Why avoid var? It’s function-scoped, not block-scoped, and hoisted. This leads to confusing bugs. Modern JavaScript uses const and let.

3. Data Types

JavaScript has 8 data types: 7 primitives and 1 object type.

Primitive Types

TypeExampleNotes
number42, 3.14, Infinity, NaNAll numbers are 64-bit floats
bigint9007199254740993nFor integers beyond safe range
string'hello', "world", `template`Immutable sequence of characters
booleantrue, falseLogical values
undefinedundefinedVariable declared but not assigned
nullnullIntentional absence of value
symbolSymbol('id')Unique identifiers (ES6)
let age = 25;              // number
let price = 19.99;         // number (no separate float type)
let name = 'Alice';        // string
let isActive = true;       // boolean
let nothing = null;        // null
let notDefined;            // undefined
let id = Symbol('id');     // symbol
let bigNumber = 9007199254740993n; // bigint

Reference Type: Object

Everything that’s not a primitive is an Object. This includes arrays, functions, dates, and regular objects.
const person = { name: 'Alice', age: 25 };
const numbers = [1, 2, 3];
const greet = function() { return 'Hello'; };
const today = new Date();

4. Type Coercion

JavaScript tries to be helpful by automatically converting types. This can lead to unexpected results.

Implicit Coercion (Automatic)

'5' + 3;      // '53' (number → string, concatenation)
'5' - 3;      // 2 (string → number, subtraction)
'5' * '2';    // 10 (both → numbers)
true + true;  // 2 (true → 1)
[] + {};      // '[object Object]' (both → strings)

Explicit Coercion (Intentional)

Number('42');     // 42
String(42);       // '42'
Boolean(0);       // false
Boolean('hello'); // true
parseInt('42px'); // 42 (parses until non-digit)

Truthy & Falsy Values

In boolean context, values are coerced to true or false. Falsy values (evaluate to false):
  • false, 0, -0, 0n, '', null, undefined, NaN
Everything else is truthy (including [], {}, '0').
if ('') console.log('truthy');   // Not printed
if ([]) console.log('truthy');   // Printed! Empty array is truthy

5. Operators

Comparison: == vs ===

Always use === (strict equality). It checks value AND type.
5 == '5';    // true (type coercion happens)
5 === '5';   // false (different types)

null == undefined;  // true
null === undefined; // false

Logical Operators

// AND: Returns first falsy or last value
true && 'hello';  // 'hello'
false && 'hello'; // false

// OR: Returns first truthy or last value
null || 'default';  // 'default'
'value' || 'default'; // 'value'

// Nullish Coalescing (ES2020): Only null/undefined
null ?? 'default';  // 'default'
0 ?? 'default';     // 0 (0 is not null/undefined)
'' ?? 'default';    // '' (empty string is not null/undefined)

Optional Chaining (ES2020)

Safely access nested properties without checking each level.
const user = { profile: { name: 'Alice' } };

// Old way
const name = user && user.profile && user.profile.name;

// New way
const name = user?.profile?.name; // 'Alice'
const age = user?.profile?.age;   // undefined (no error)

6. Control Flow

Conditionals

if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else {
    grade = 'C';
}

// Ternary operator
const status = age >= 18 ? 'Adult' : 'Minor';

Switch

switch (day) {
    case 'Monday':
    case 'Tuesday':
        console.log('Weekday');
        break;
    case 'Saturday':
    case 'Sunday':
        console.log('Weekend');
        break;
    default:
        console.log('Unknown');
}

Loops

// For loop
for (let i = 0; i < 5; i++) {
    console.log(i);
}

// For...of (iterate over values) — Use this!
const fruits = ['apple', 'banana', 'cherry'];
for (const fruit of fruits) {
    console.log(fruit);
}

// For...in (iterate over keys/indices) — Avoid for arrays
for (const index in fruits) {
    console.log(index); // '0', '1', '2' (strings!)
}

// While
let count = 0;
while (count < 3) {
    console.log(count++);
}

Summary

  • Variables: Use const by default, let when needed. Avoid var.
  • Types: 7 primitives (number, string, boolean, null, undefined, symbol, bigint) + Object.
  • Coercion: JavaScript auto-converts types. Use === to avoid surprises.
  • Operators: Use ?? for null/undefined, ?. for safe property access.
Next, we’ll dive deep into Functions & Scope, the heart of JavaScript.