JavaScript Fundamentals: Complete Guide

JavaScript Fundamentals: Complete Guide

JavaScript is the programming language of the web. It's a versatile, high-level language that runs in browsers and on servers, making it essential for modern web development.

What is JavaScript?

JavaScript is a dynamic, interpreted programming language that conforms to the ECMAScript specification. It's primarily known for adding interactivity to web pages, but it's also used in server-side development, mobile apps, and desktop applications.

Key Features

  • Dynamic Typing: Variables can hold values of any type
  • First-class Functions: Functions are treated as values
  • Prototype-based: Uses prototypes instead of classes for inheritance
  • Event-driven: Responds to user interactions and system events
  • Asynchronous: Supports non-blocking operations

Setting Up JavaScript

In HTML

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript Example</title>
</head>
<body>
    <script>
        console.log("Hello, World!");
    </script>
</body>
</html>

External File

<script src="script.js"></script>

Node.js Environment

# Install Node.js from https://nodejs.org
node script.js

Variables and Data Types

Variable Declarations

// var (function-scoped, can be redeclared)
var name = "John";

// let (block-scoped, cannot be redeclared)
let age = 25;

// const (block-scoped, cannot be reassigned)
const PI = 3.14159;

Data Types

// Primitive Types
let string = "Hello, World!";
let number = 42;
let boolean = true;
let undefinedVar = undefined;
let nullVar = null;
let symbol = Symbol('id');

// Object Types
let object = { name: "John", age: 25 };
let array = [1, 2, 3, 4, 5];
let function = function() { return "Hello!"; };

Functions

Function Declarations

function greet(name) {
    return `Hello, ${name}!`;
}

// Function Expression
const greet = function(name) {
    return `Hello, ${name}!`;
};

// Arrow Function (ES6+)
const greet = (name) => `Hello, ${name}!`;

// Arrow function with multiple parameters
const add = (a, b) => a + b;

// Arrow function with block body
const multiply = (a, b) => {
    const result = a * b;
    return result;
};

Function Parameters

// Default parameters
function greet(name = "World") {
    return `Hello, ${name}!`;
}

// Rest parameters
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

// Destructuring parameters
function displayUser({ name, age, email }) {
    console.log(`Name: ${name}, Age: ${age}, Email: ${email}`);
}

Objects and Arrays

Objects

// Object literal
const person = {
    name: "John Doe",
    age: 30,
    email: "john@example.com",

    // Method
    greet() {
        return `Hello, I'm ${this.name}`;
    },

    // Arrow function (no 'this' binding)
    greetArrow: () => {
        return `Hello, I'm ${this.name}`; // 'this' refers to global object
    }
};

// Accessing properties
console.log(person.name);        // Dot notation
console.log(person["age"]);      // Bracket notation

// Adding properties
person.city = "New York";
person["country"] = "USA";

// Object destructuring
const { name, age, email } = person;

Arrays

// Array creation
const fruits = ["apple", "banana", "orange"];
const numbers = new Array(1, 2, 3, 4, 5);

// Array methods
fruits.push("grape");           // Add to end
fruits.pop();                   // Remove from end
fruits.unshift("strawberry");   // Add to beginning
fruits.shift();                 // Remove from beginning

// Array iteration
fruits.forEach(fruit => console.log(fruit));

// Array transformation
const upperFruits = fruits.map(fruit => fruit.toUpperCase());
const longFruits = fruits.filter(fruit => fruit.length > 5);

// Array destructuring
const [first, second, ...rest] = fruits;

Control Flow

Conditionals

// if/else
if (age >= 18) {
    console.log("Adult");
} else if (age >= 13) {
    console.log("Teenager");
} else {
    console.log("Child");
}

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

// Switch statement
switch (day) {
    case "Monday":
        console.log("Start of work week");
        break;
    case "Friday":
        console.log("TGIF!");
        break;
    default:
        console.log("Regular day");
}

Loops

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

// for...of loop (arrays, strings)
for (const fruit of fruits) {
    console.log(fruit);
}

// for...in loop (objects)
for (const key in person) {
    console.log(`${key}: ${person[key]}`);
}

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

// do...while loop
do {
    console.log("This runs at least once");
} while (false);

ES6+ Features

Template Literals

const name = "John";
const age = 25;

// String interpolation
const message = `Hello, my name is ${name} and I'm ${age} years old.`;

// Multi-line strings
const html = `
    <div>
        <h1>${name}</h1>
        <p>Age: ${age}</p>
    </div>
`;

Destructuring

// Array destructuring
const [first, second, third] = [1, 2, 3];

// Object destructuring
const { name, age, email } = person;

// Destructuring with default values
const { name = "Anonymous", age = 0 } = person;

// Destructuring in function parameters
function createUser({ name, age, email = "no-email@example.com" }) {
    return { name, age, email };
}

Spread Operator

// Array spreading
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];

// Object spreading
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const combined = { ...obj1, ...obj2 };

// Function arguments
function sum(a, b, c) {
    return a + b + c;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));

Classes

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        return `Hello, I'm ${this.name}`;
    }

    // Static method
    static createAdult(name) {
        return new Person(name, 18);
    }
}

class Student extends Person {
    constructor(name, age, grade) {
        super(name, age);
        this.grade = grade;
    }

    study() {
        return `${this.name} is studying`;
    }
}

const student = new Student("Alice", 20, "A");
console.log(student.greet());
console.log(student.study());

Asynchronous JavaScript

Promises

// Creating a promise
const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const success = Math.random() > 0.5;
            if (success) {
                resolve("Data fetched successfully");
            } else {
                reject("Failed to fetch data");
            }
        }, 1000);
    });
};

// Using promises
fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error))
    .finally(() => console.log("Promise completed"));

Async/Await

// Async function
async function fetchUserData(userId) {
    try {
        const response = await fetch(`/api/users/${userId}`);
        const user = await response.json();
        return user;
    } catch (error) {
        console.error("Error fetching user:", error);
        throw error;
    }
}

// Using async/await
async function displayUser(userId) {
    try {
        const user = await fetchUserData(userId);
        console.log(`User: ${user.name}`);
    } catch (error) {
        console.error("Failed to display user:", error);
    }
}

Fetch API

// GET request
async function getUsers() {
    try {
        const response = await fetch('/api/users');
        const users = await response.json();
        return users;
    } catch (error) {
        console.error('Error:', error);
    }
}

// POST request
async function createUser(userData) {
    try {
        const response = await fetch('/api/users', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(userData)
        });
        const newUser = await response.json();
        return newUser;
    } catch (error) {
        console.error('Error:', error);
    }
}

DOM Manipulation

// Selecting elements
const element = document.getElementById('myId');
const elements = document.querySelectorAll('.myClass');
const firstElement = document.querySelector('.myClass');

// Creating elements
const newDiv = document.createElement('div');
newDiv.textContent = 'Hello, World!';
newDiv.className = 'my-class';

// Adding to DOM
document.body.appendChild(newDiv);

// Event listeners
element.addEventListener('click', (event) => {
    console.log('Element clicked!', event.target);
});

// Form handling
const form = document.querySelector('#myForm');
form.addEventListener('submit', (event) => {
    event.preventDefault();
    const formData = new FormData(form);
    const data = Object.fromEntries(formData);
    console.log(data);
});

Error Handling

// try/catch
try {
    const result = riskyOperation();
    console.log(result);
} catch (error) {
    console.error('An error occurred:', error.message);
} finally {
    console.log('This always runs');
}

// Custom errors
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = 'ValidationError';
    }
}

function validateAge(age) {
    if (age < 0) {
        throw new ValidationError('Age cannot be negative');
    }
    if (age > 150) {
        throw new ValidationError('Age seems unrealistic');
    }
    return true;
}

Modules

// math.js (exporting)
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

export default function multiply(a, b) {
    return a * b;
}

// main.js (importing)
import multiply, { add, subtract } from './math.js';

console.log(add(2, 3));        // 5
console.log(subtract(5, 2));   // 3
console.log(multiply(4, 5));   // 20

Best Practices

1. Use const and let instead of var

// Good
const PI = 3.14159;
let counter = 0;

// Bad
var PI = 3.14159;
var counter = 0;

2. Use meaningful variable names

// Good
const userEmail = "user@example.com";
const isUserLoggedIn = true;

// Bad
const e = "user@example.com";
const flag = true;

3. Use arrow functions for short functions

// Good
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);

// Also good for longer functions
const processUser = (user) => {
    const processedUser = {
        ...user,
        fullName: `${user.firstName} ${user.lastName}`,
        isActive: true
    };
    return processedUser;
};

4. Use template literals

// Good
const message = `Hello, ${name}! Welcome to ${appName}.`;

// Bad
const message = "Hello, " + name + "! Welcome to " + appName + ".";

Resources

JavaScript is a powerful and flexible language that continues to evolve. Keep practicing and building projects to master it! 🚀

/* */