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! 🚀