Basic Syntax & Fundamentals

45 min read Beginner

Master the building blocks of JavaScript: variables, data types, operators, and expressions. These fundamentals form the foundation for everything you'll build.

Variables: Storing Data

Variables are containers that store data values. Think of them as labeled boxes where you can put information and retrieve it later using the label.

JavaScript provides three ways to declare variables:

let - For Changeable Values

Use let when you need a variable whose value can change.

script.js
// Declare a variable
let age = 25;
console.log(age); // Output: 25

// Change the value
age = 26;
console.log(age); // Output: 26

// Declare without initial value
let score;
console.log(score); // Output: undefined

score = 100;
console.log(score); // Output: 100

const - For Fixed Values

Use const for values that should never change after assignment. This is the preferred choice when you know the value won't need to be reassigned.

script.js
// Constants cannot be reassigned
const PI = 3.14159;
const APP_NAME = "My Application";
const MAX_USERS = 100;

console.log(PI); // Output: 3.14159

// This will cause an error:
// PI = 3.14; // TypeError: Assignment to constant variable

// const must be initialized when declared
// const x; // SyntaxError: Missing initializer

const with Objects and Arrays

While you can't reassign a const, you CAN modify the contents of objects and arrays. The reference is constant, not the data inside.

script.js
// const with arrays - modifying content is allowed
const colors = ["red", "green"];
colors.push("blue"); // This works!
console.log(colors); // ["red", "green", "blue"]

// colors = ["yellow"]; // Error: can't reassign

// const with objects - modifying properties is allowed
const user = { name: "John" };
user.name = "Jane"; // This works!
user.age = 30;      // This works too!
console.log(user);  // { name: "Jane", age: 30 }

// user = { name: "Bob" }; // Error: can't reassign

var - The Legacy Way

var is the original way to declare variables in JavaScript. It's still supported but has quirks that can cause bugs.

script.js
// var works similarly to let for basic usage
var message = "Hello";
message = "Hi";
console.log(message); // "Hi"

// But var has different scoping rules (function-scoped)
// We'll cover this in detail in the Functions topic

Best Practice

Use const by default. Only use let when you know the value needs to change. Avoid var in modern JavaScript.

Variable Naming Rules

script.js
// Valid variable names
let firstName = "John";      // camelCase (recommended)
let last_name = "Doe";       // snake_case
let _private = "secret";     // can start with underscore
let $element = "jQuery";     // can start with $
let café = "coffee";         // Unicode letters allowed
let π = 3.14159;             // Unicode symbols work too

// Invalid variable names
// let 123abc = "error";     // Cannot start with number
// let my-var = "error";     // Hyphens not allowed
// let let = "error";        // Cannot use reserved words

// Naming conventions
const MAX_SIZE = 100;        // UPPER_SNAKE_CASE for constants
let userAge = 25;            // camelCase for variables
let isActive = true;         // prefix booleans with is/has/can

Naming Best Practices

Good variable names make your code self-documenting. Follow these conventions used by professional developers:

Naming Conventions by Type
// 1. Variables and Functions: camelCase
let userName = "john_doe";
let totalPrice = 99.99;
function calculateTax(amount) { /* ... */ }
function getUserById(id) { /* ... */ }

// 2. Constants: UPPER_SNAKE_CASE
const API_BASE_URL = "https://api.example.com";
const MAX_RETRY_ATTEMPTS = 3;
const DEFAULT_TIMEOUT_MS = 5000;

// 3. Classes: PascalCase
class UserAccount { /* ... */ }
class ShoppingCart { /* ... */ }
class PaymentProcessor { /* ... */ }

// 4. Boolean variables: is/has/can/should prefix
let isLoggedIn = true;
let hasPermission = false;
let canEdit = true;
let shouldUpdate = false;

// 5. Arrays: plural nouns
let users = [];
let productItems = [];
let selectedColors = [];

// 6. Functions: verb + noun (action-oriented)
function fetchUserData() { /* ... */ }
function validateEmail(email) { /* ... */ }
function sendNotification(message) { /* ... */ }

// 7. Event handlers: handle + EventName
function handleClick(event) { /* ... */ }
function handleFormSubmit(event) { /* ... */ }
function handleMouseEnter(event) { /* ... */ }

// 8. Private members (convention): underscore prefix
class User {
    _password = "";  // Indicates "private" (convention only)
    #reallyPrivate;  // Actually private (ES2022)
}

Reserved Words

JavaScript has reserved keywords that cannot be used as variable names. These words have special meaning in the language:

Reserved Keywords
// ❌ These will cause errors if used as variable names:

// Control flow
// break, case, catch, continue, default, do, else, finally,
// for, if, return, switch, throw, try, while

// Declaration
// class, const, function, let, var

// Values
// false, null, true

// Operators
// delete, in, instanceof, new, typeof, void

// Other
// debugger, export, extends, import, super, this, with

// ❌ Also reserved for future use:
// await, enum, implements, interface, package, private,
// protected, public, static, yield

// ✅ These are NOT reserved and can be used (but avoid them):
let undefined = 5;  // Works but terrible idea!
let NaN = "hello";  // Works but confusing!
let Infinity = 42;  // Works but please don't!

Avoid Shadowing Built-ins

While you technically CAN use names like name, length, or status, they may conflict with browser properties. Be specific: use userName instead of name.

The Semicolon Debate

In JavaScript, semicolons are technically optional in many cases due to Automatic Semicolon Insertion (ASI). However, this feature can cause unexpected bugs.

How ASI Works

Automatic Semicolon Insertion
// JavaScript automatically inserts semicolons in these cases:

// 1. At the end of lines before a line terminator
let a = 1
let b = 2
// Becomes: let a = 1; let b = 2;

// 2. After return, throw, break, continue with line break
function getName() {
    return
    "John"  // ASI inserts semicolon after return!
}
console.log(getName()); // undefined (not "John"!)

// 3. Before closing braces
function test() {
    return true
}  // ASI inserts semicolon before }

ASI Gotchas

Common ASI Problems
// ❌ Problem 1: Return statement with line break
function getUser() {
    return
    {
        name: "John",
        age: 30
    }
}
console.log(getUser()); // undefined!

// ✅ Solution: Keep opening brace on same line
function getUser() {
    return {
        name: "John",
        age: 30
    };
}

// ❌ Problem 2: IIFE after another statement
const message = "Hello"
(function() {
    console.log("IIFE");
})()
// Error: "Hello" is not a function!

// ✅ Solution: Use semicolons
const message = "Hello";
(function() {
    console.log("IIFE");
})();

// ❌ Problem 3: Array after statement
const a = 1
[1, 2, 3].forEach(n => console.log(n))
// Error: Cannot read property 'forEach' of undefined

// ✅ Solution: Prefix with semicolon when needed
const a = 1
;[1, 2, 3].forEach(n => console.log(n))

Team Decision

Whether to use semicolons is a team/project decision. Many projects use tools like Prettier or ESLint to enforce a consistent style automatically. The most important thing is consistency within your codebase.

Code Style Guides

Professional teams follow code style guides to ensure consistent, readable code. Here are the most popular ones:

Popular JavaScript Style Guides

Key Style Recommendations

Common Style Rules
// 1. Indentation: 2 spaces (common) or 4 spaces
function example() {
  const name = "John"; // 2-space indent
}

// 2. Quotes: Be consistent (single or double)
const single = 'Hello';  // Airbnb prefers single
const double = "Hello";  // Google allows both
const template = `Hello ${name}`; // Template literals for interpolation

// 3. Trailing commas: Help with cleaner git diffs
const user = {
  name: "John",
  age: 30,  // Trailing comma
};

const colors = [
  "red",
  "green",
  "blue",  // Trailing comma
];

// 4. Spacing around operators
const sum = a + b;  // ✅ Spaces around operators
const sum = a+b;    // ❌ Hard to read

// 5. Spacing in objects
const obj = { name: "John", age: 30 };  // ✅ Spaces after { and before }
const obj = {name:"John",age:30};       // ❌ Cramped

// 6. Function declarations
// Named function
function greet(name) {
  return `Hello, ${name}!`;
}

// Arrow function for callbacks
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

// 7. Max line length: 80-120 characters
// Break long lines for readability
const longString = "This is a very long string that " +
  "spans multiple lines for better readability.";

Data Types

JavaScript has eight data types. Seven are "primitive" (simple values) and one is "complex" (objects).

Primitive Types

1. String - Text Data

script.js
// Three ways to create strings
const single = 'Hello';           // Single quotes
const double = "World";           // Double quotes
const backtick = `Hello World`;   // Template literals (backticks)

// String length
console.log(single.length); // 5

// Accessing characters
console.log(single[0]);     // "H"
console.log(single[4]);     // "o"

// Template literals - embed expressions
const name = "Alice";
const age = 25;
const greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting); // "Hello, Alice! You are 25 years old."

// Multi-line strings (only with backticks)
const multiLine = `
    This is line 1
    This is line 2
    This is line 3
`;

// Escape characters
const escaped = "She said \"Hello!\"";  // She said "Hello!"
const newLine = "Line 1\nLine 2";       // \n = new line
const tab = "Column1\tColumn2";         // \t = tab

2. Number - Numeric Data

script.js
// Integers and decimals are both "number" type
const integer = 42;
const decimal = 3.14;
const negative = -10;

// Scientific notation
const big = 1.5e6;     // 1,500,000
const small = 1.5e-6;  // 0.0000015

// Special numeric values
const infinity = Infinity;
const negInfinity = -Infinity;
const notANumber = NaN;  // Result of invalid math

// Checking for special values
console.log(isNaN(NaN));          // true
console.log(isFinite(100));       // true
console.log(isFinite(Infinity));  // false

// Number methods
const num = 3.14159;
console.log(num.toFixed(2));      // "3.14" (string)
console.log(num.toPrecision(3));  // "3.14" (string)

// Parsing strings to numbers
console.log(parseInt("42"));       // 42
console.log(parseFloat("3.14"));   // 3.14
console.log(Number("123"));        // 123
console.log(+"456");               // 456 (unary plus)

3. Boolean - True or False

script.js
// Boolean values
const isActive = true;
const isComplete = false;

// Comparisons return booleans
console.log(5 > 3);   // true
console.log(5 < 3);   // false
console.log(5 === 5); // true

// Truthy and Falsy values
// Falsy: false, 0, "", null, undefined, NaN
// Truthy: everything else

console.log(Boolean(0));         // false
console.log(Boolean(""));        // false
console.log(Boolean(null));      // false
console.log(Boolean(undefined)); // false

console.log(Boolean(1));         // true
console.log(Boolean("hello"));   // true
console.log(Boolean([]));        // true (empty array is truthy!)
console.log(Boolean({}));        // true (empty object is truthy!)

4. undefined - No Value Assigned

script.js
// Variable declared but not assigned
let x;
console.log(x);        // undefined
console.log(typeof x); // "undefined"

// Function with no return value
function doNothing() {}
console.log(doNothing()); // undefined

// Accessing non-existent property
const obj = { name: "John" };
console.log(obj.age); // undefined

5. null - Intentional Empty Value

script.js
// null means "no value" intentionally
let selectedUser = null;
console.log(selectedUser); // null

// typeof null is "object" (historical bug)
console.log(typeof null); // "object"

// Checking for null
console.log(selectedUser === null); // true

// null vs undefined
let a;           // undefined (not assigned)
let b = null;    // null (intentionally empty)

console.log(a == b);  // true (loose equality)
console.log(a === b); // false (strict equality)

6. Symbol - Unique Identifiers (ES6)

script.js
// Symbols are unique and immutable
const sym1 = Symbol("description");
const sym2 = Symbol("description");

console.log(sym1 === sym2); // false (always unique!)

// Useful for object property keys
const id = Symbol("id");
const user = {
    name: "John",
    [id]: 12345
};

console.log(user[id]); // 12345

7. BigInt - Large Integers (ES2020)

script.js
// Regular numbers have limits
const maxSafe = Number.MAX_SAFE_INTEGER;
console.log(maxSafe); // 9007199254740991

// BigInt for larger numbers (add 'n' suffix)
const bigNum = 9007199254740991n;
const anotherBig = BigInt("9999999999999999999999");

console.log(bigNum + 1n); // 9007199254740992n

// Cannot mix BigInt and regular numbers
// console.log(bigNum + 1); // TypeError!

The typeof Operator

script.js
// typeof returns a string describing the type
console.log(typeof "hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol());    // "symbol"
console.log(typeof 10n);         // "bigint"

// Quirks
console.log(typeof null);        // "object" (historical bug)
console.log(typeof []);          // "object"
console.log(typeof {});          // "object"
console.log(typeof function(){}); // "function"

Operators

Arithmetic Operators

script.js
// Basic arithmetic
console.log(10 + 5);  // 15 (addition)
console.log(10 - 5);  // 5  (subtraction)
console.log(10 * 5);  // 50 (multiplication)
console.log(10 / 5);  // 2  (division)
console.log(10 % 3);  // 1  (modulus/remainder)
console.log(2 ** 3);  // 8  (exponentiation)

// Order of operations (PEMDAS)
console.log(2 + 3 * 4);     // 14 (not 20)
console.log((2 + 3) * 4);   // 20

// Increment and decrement
let count = 5;
count++;        // count is now 6
count--;        // count is now 5

// Pre vs post increment
let a = 5;
console.log(a++); // 5 (returns old value, then increments)
console.log(a);   // 6

let b = 5;
console.log(++b); // 6 (increments first, then returns)
console.log(b);   // 6

Comparison Operators

script.js
// Comparison operators return booleans
console.log(5 > 3);   // true  (greater than)
console.log(5 < 3);   // false (less than)
console.log(5 >= 5);  // true  (greater than or equal)
console.log(5 <= 4);  // false (less than or equal)

// Equality: == vs ===
console.log(5 == "5");   // true  (loose: converts types)
console.log(5 === "5");  // false (strict: no conversion)
console.log(5 === 5);    // true

// Inequality: != vs !==
console.log(5 != "5");   // false (loose)
console.log(5 !== "5");  // true  (strict)

// String comparison (lexicographic)
console.log("apple" < "banana");  // true
console.log("a" < "b");           // true
console.log("2" > "10");          // true (string comparison!)

Best Practice

Always use === and !== (strict equality) to avoid unexpected type coercion bugs.

Logical Operators

script.js
// AND (&&) - both must be true
console.log(true && true);   // true
console.log(true && false);  // false
console.log(5 > 3 && 10 > 5); // true

// OR (||) - at least one must be true
console.log(true || false);  // true
console.log(false || false); // false
console.log(5 > 10 || 10 > 5); // true

// NOT (!) - inverts the boolean
console.log(!true);  // false
console.log(!false); // true
console.log(!0);     // true (0 is falsy)
console.log(!"");    // true (empty string is falsy)

// Short-circuit evaluation
const user = null;
const name = user && user.name; // undefined (doesn't error)
const defaultName = name || "Guest"; // "Guest"

// Nullish coalescing (??) - ES2020
const value = null ?? "default";  // "default"
const zero = 0 ?? "default";      // 0 (only null/undefined trigger default)

Assignment Operators

script.js
let x = 10;

x += 5;   // x = x + 5  → 15
x -= 3;   // x = x - 3  → 12
x *= 2;   // x = x * 2  → 24
x /= 4;   // x = x / 4  → 6
x %= 4;   // x = x % 4  → 2
x **= 3;  // x = x ** 3 → 8

// Logical assignment (ES2021)
let a = null;
a ||= "default";  // a = a || "default" → "default"

let b = "hello";
b &&= "world";    // b = b && "world" → "world"

let c = null;
c ??= "fallback"; // c = c ?? "fallback" → "fallback"

Type Conversion

script.js
// To String
String(123);          // "123"
(123).toString();     // "123"
123 + "";             // "123"

// To Number
Number("123");        // 123
Number("hello");      // NaN
Number(true);         // 1
Number(false);        // 0
parseInt("42px");     // 42
parseFloat("3.14");   // 3.14
+"123";               // 123 (unary plus)

// To Boolean
Boolean(1);           // true
Boolean(0);           // false
Boolean("hello");     // true
Boolean("");          // false
!!value;              // Convert to boolean (double NOT)

// Automatic coercion (be careful!)
console.log("5" + 3);     // "53" (string concatenation)
console.log("5" - 3);     // 2   (subtraction converts to number)
console.log("5" * "2");   // 10  (multiplication converts)
console.log(true + true); // 2   (booleans become 1)

Type Coercion Deep Dive

Type coercion is JavaScript's automatic conversion of values from one type to another. Understanding it helps you avoid subtle bugs.

String Coercion

String Coercion Examples
// The + operator with a string converts other operand to string
console.log("Hello " + 42);        // "Hello 42"
console.log("Value: " + true);     // "Value: true"
console.log("Items: " + null);     // "Items: null"
console.log("Count: " + undefined); // "Count: undefined"
console.log("" + 123);             // "123"

// Template literals also trigger string coercion
const num = 42;
console.log(`Number: ${num}`);     // "Number: 42"
console.log(`Bool: ${true}`);      // "Bool: true"

// Array to string
console.log([1, 2, 3] + "");       // "1,2,3"
console.log("Items: " + [1, 2]);   // "Items: 1,2"

// Object to string (uses toString method)
console.log({} + "");              // "[object Object]"
console.log({name: "John"} + "");  // "[object Object]"

Number Coercion

Number Coercion Examples
// Math operators (except +) convert to numbers
console.log("10" - 5);     // 5
console.log("10" * "2");   // 20
console.log("10" / 2);     // 5
console.log("10" % 3);     // 1

// Comparison operators
console.log("10" > 5);     // true (string converted to number)
console.log("10" > "5");   // false! (string comparison, "1" < "5")

// Unary + operator converts to number
console.log(+"42");        // 42
console.log(+true);        // 1
console.log(+false);       // 0
console.log(+"");          // 0
console.log(+null);        // 0
console.log(+undefined);   // NaN
console.log(+"hello");     // NaN

// Boolean to number
console.log(true * 10);    // 10
console.log(false * 10);   // 0

// null and undefined
console.log(null * 10);    // 0 (null becomes 0)
console.log(undefined * 10); // NaN (undefined becomes NaN)

Boolean Coercion

Boolean Coercion (Truthy/Falsy)
// FALSY values (convert to false):
if (false) {}      // false
if (0) {}          // false
if (-0) {}         // false
if (0n) {}         // false (BigInt zero)
if ("") {}         // false (empty string)
if (null) {}       // false
if (undefined) {}  // false
if (NaN) {}        // false

// TRUTHY values (everything else converts to true):
if (true) {}       // true
if (1) {}          // true
if (-1) {}         // true (any non-zero number)
if ("hello") {}    // true (any non-empty string)
if ("0") {}        // true! (string "0" is truthy)
if ("false") {}    // true! (string "false" is truthy)
if ([]) {}         // true! (empty array is truthy)
if ({}) {}         // true! (empty object is truthy)
if (function(){}) {} // true (functions are truthy)

// Double NOT for explicit boolean conversion
console.log(!!"hello");  // true
console.log(!!"");       // false
console.log(!!0);        // false
console.log(!!1);        // true

Equality Coercion Gotchas

== vs === Examples
// Surprising == comparisons (all true!)
console.log(0 == false);        // true
console.log("" == false);       // true
console.log(null == undefined); // true
console.log("0" == false);      // true
console.log([] == false);       // true
console.log([[]] == 0);         // true
console.log([1] == 1);          // true

// Even more confusing
console.log([] == ![]);         // true! (wat?)
console.log([] == 0);           // true
console.log([] == "");          // true

// === avoids all this confusion
console.log(0 === false);       // false
console.log("" === false);      // false
console.log(null === undefined); // false
console.log([] === false);      // false

// When to use == (rarely)
// Only for null/undefined check:
if (value == null) {
    // Catches both null and undefined
}
// Same as:
if (value === null || value === undefined) {
    // More explicit but longer
}

The Golden Rule

Always use === and !== unless you have a specific reason to use ==. Type coercion in comparisons is one of the most common sources of bugs in JavaScript.

Comments

script.js
// This is a single-line comment

/*
   This is a multi-line comment.
   It can span multiple lines.
   Useful for longer explanations.
*/

/**
 * JSDoc comment - used for documentation
 * @param {string} name - The user's name
 * @returns {string} A greeting message
 */
function greet(name) {
    return `Hello, ${name}!`;
}

// Comments are ignored by JavaScript
let x = 5; // This comment explains the variable

// Use comments to temporarily disable code
// console.log("This won't run");

Summary

In this chapter, you learned the fundamental building blocks of JavaScript:

Next Steps

Now that you understand variables and data types, you're ready to learn how to control the flow of your programs with conditionals and loops!