// ---------------------------------------------------------------------------------
// JavaScript Reference and Guide
//
// ReferenceCollection.com
// Licensed under CC BY-SA
// ---------------------------------------------------------------------------------
// TABLE OF CONTENTS
// -----------------
// 1. Introduction
// 2. Basic Syntax and Structure
// 3. Modules
// 4. Variables and Data Types
// 5. Operators
// 6. Control Flow Statements
// 7. Arrays
// 8. Functions
// 9. Objects
// 10. DOM Manipulation
// 11. Events
// 12. Asynchronous JavaScript
// 13. Error Handling
// 14. Classes
// 15. Iterators and Generators
// 16. Debugging
// ---------------------------------------------------------------------------------
// 1. Introduction
// ---------------------------------------------------------------------------------
// JavaScript is a versatile, high-level, dynamic programming language primarily
// known for adding interactivity to websites. It's a core technology of the web,
// alongside HTML and CSS. It is also used in server-side environments (Node.js),
// mobile app development (React Native), and even desktop applications (Electron).
// Key Features:
// - Dynamic Typing: Variables can hold different types of data
// - First-class Functions: Functions can be assigned to variables
// - Event-Driven: Responds to user actions and system events
// - Rich Ecosystem: Vast collection of libraries and frameworks
// - Cross-Platform: Runs in browsers, servers, and various environments
// - Multi-Paradigm: Supports procedural, object-oriented, and functional programming
// Getting Started:
// - No installation is required for browser-based JavaScript.
// - For server-side development, install Node.js (which includes npm, the Node
// Package Manager).
// - Use a text editor or IDE (Integrated Development Environment) like VS Code.
// - JavaScript code can be embedded in HTML files using `<script>` tags or linked
// as separate `.js` files.
// JavaScript Engine:
// A program that executes JavaScript code. Popular engines include:
// - V8 (Chrome, Node.js, Edge)
// - SpiderMonkey (Firefox)
// - JavaScriptCore (Safari)
// ECMAScript:
// The standard upon which JavaScript is based. It defines the core features.
// New versions (ES6, ES2017, ES2020, etc.) introduce new features and improvements.
// It's often referred to as "ES" followed by the year of release.
// ---------------------------------------------------------------------------------
// 2. Basic Syntax and Structure
// ---------------------------------------------------------------------------------
// JavaScript programs are made up of statements, expressions, and declarations.
// Basic Elements:
// - Statements: Instructions that perform actions.
// - Expressions: Produce values.
// - Variables: Named storage for data.
// - Functions: Reusable blocks of code.
// - Objects: Collections of related data and functions.
// Syntax Rules:
// - Case-Sensitive: `myVariable` and `myvariable` are distinct.
// - Semicolons: Generally optional, but highly recommended to avoid ambiguity.
// - Comments: `//` for single-line, `/* ... */` for multi-line.
// - Whitespace: Mostly ignored, but crucial for readability.
// - Strict Mode: ` "use strict";` at the beginning of a file or function enables
// stricter error handling and prevents some unsafe actions.
// Example:
"use strict"; // Enable strict mode
function greet(name) { // Function declaration
return `Hello, ${name}!`; // String interpolation
}
console.log(greet("World")); // Function call and output
// ---------------------------------------------------------------------------------
// 3. Modules
// ---------------------------------------------------------------------------------
// Modules help organize code into reusable units, preventing naming conflicts and
// improving maintainability.
// Key Concepts:
// - `export`: Makes variables, functions, or classes available to other modules.
// - `import`: Brings functionality from other modules into the current module.
// Example (module1.js):
// Exporting a constant
export const myConstant = 42;
// Exporting a function
export function myFunction(x) {
return x * 2;
}
// Exporting a class
export class MyClass {
constructor(value) {
this.value = value;
}
}
// Default export (only one per module)
export default function myDefaultFunction() {
console.log("This is the default export.");
}
// Example (module2.js):
// Importing specific exports
import { myConstant, myFunction } from './module1.js';
// Importing the default export
import myDefaultFunction from './module1.js';
// Importing everything with a namespace
import * as MyModule from './module1.js';
console.log(myConstant); // Accessing the imported constant: 42
console.log(myFunction(5)); // Calling the imported function: 10
myDefaultFunction(); // Calling the default export function: "This is the default export."
console.log(MyModule.myConstant) // Accessing using the namespace: 42
// ---------------------------------------------------------------------------------
// 4. Variables and Data Types
// ---------------------------------------------------------------------------------
// Variables are used to store data. JavaScript is dynamically typed, meaning
// you don't need to specify the type of a variable when you declare it.
// Variable Declarations:
// - let: Block-scoped, can be reassigned.
// - const: Block-scoped, must be initialized, cannot be reassigned.
// - var: Function-scoped (global if declared outside any function).
// Avoid using var in modern JavaScript.
// Primitive Data Types:
// - `number`: Numeric values (integers and floating-point numbers).
// - `string`: Textual data.
// - `boolean`: `true` or `false`.
// - `undefined`: Represents a variable that is declared but not assigned a value.
// - `null`: Represents the intentional absence of any object value.
// - `symbol`: Unique and immutable values, often used as object property keys.
// - `bigint`: Represents integers larger than the `number` type can handle.
// Reference Data Types:
// - `object`: Collections of key-value pairs.
// - `array`: Ordered lists of values.
// - `function`: Reusable blocks of code.
// Examples:
let userAge = 30; // Number
const name = "Alice"; // String
let isLoggedIn = true; // Boolean
let city; // Undefined (no value assigned)
let address = null; // Null (intentional absence of value)
const id = Symbol("uniqueId"); // Symbol
let veryLargeNumber = 12345678901234567890n; // BigInt
let user = { // Object
firstName: "Bob",
lastName: "Smith",
age: 25
};
let colors = ["red", "green", "blue"];// Array
function add(a, b) { // Function
return a + b;
}
// Dynamic Typing Example:
let myVar = 10; // myVar is a number
myVar = "Hello"; // myVar is now a string
myVar = true; // myVar is now a boolean
// Type Coercion (Implicit Type Conversion):
let result = 5 + "5"; // "55" (number is coerced to a string)
let result2 = "5" * 2; // 10 (string is coerced to a number)
// Explicit Type Conversion:
let numStr = "123";
let numInt = parseInt(numStr); // Converts string to integer: 123
let floatNum = parseFloat("3.14"); // Converts string to floating-point number: 3.14
let textStr = String(42); // Converts number to string: "42"
let bool = Boolean(0); // Converts to boolean (0 is falsy, so bool is false)
// ---------------------------------------------------------------------------------
// 5. Operators
// ---------------------------------------------------------------------------------
// Operators perform actions on values (operands).
// Arithmetic Operators:
// - `+` (Addition)
// - `-` (Subtraction)
// - `*` (Multiplication)
// - `/` (Division)
// - `%` (Modulo - remainder of division)
// - `**` (Exponentiation)
// Assignment Operators:
// - `=` (Assignment)
// - `+=` (Add and assign)
// - `-=` (Subtract and assign)
// - `*=` (Multiply and assign)
// - `/=` (Divide and assign)
// - `%=` (Modulo and assign)
// - `**=` (Exponentiate and assign)
// Comparison Operators:
// - `==` (Loose equality - checks only value, performs type coercion)
// - `===` (Strict equality - checks both value and type)
// - `!=` (Loose inequality)
// - `!==` (Strict inequality)
// - `>` (Greater than)
// - `<` (Less than)
// - `>=` (Greater than or equal to)
// - `<=` (Less than or equal to)
// Logical Operators:
// - `&&` (Logical AND)
// - `||` (Logical OR)
// - `!` (Logical NOT)
// Unary Operators:
// - `-` (Negation)
// - `+` (Unary plus - attempts to convert to a number)
// - `++` (Increment)
// - `--` (Decrement)
// - `typeof` (Returns a string indicating the type of a variable)
// - `delete` (Deletes an object property)
// - `void` (Discards a return value)
// Ternary Operator:
// - `condition ? exprIfTrue : exprIfFalse` (Conditional operator)
// Bitwise Operators: (less commonly used)
// - `&` (Bitwise AND)
// - `|` (Bitwise OR)
// - `^` (Bitwise XOR)
// - `~` (Bitwise NOT)
// - `<<` (Left shift)
// - `>>` (Right shift - sign-propagating)
// - `>>>` (Right shift - zero-fill)
// Examples:
let x = 10;
let y = 5;
// Arithmetic
let sum = x + y; // 15
let diff = x - y; // 5
let product = x * y; // 50
let quotient = x / y; // 2
let remainder = x % y; // 0
let power = x ** y; // 100000
// Assignment
x += 5; // x is now 15
y -= 2; // y is now 3
// Comparison
console.log(x == y); // false
console.log(x === "15"); // false (strict equality checks type)
console.log(x != y); // true
console.log(x > y); // true
// Logical
let a = true;
let b = false;
console.log(a && b); // false
console.log(a || b); // true
console.log(!a); // false
// Unary
let z = -x; // -15
let strNum = +"42"; // 42 (converted to number)
let preIncrement = ++x; // x is now 16, preIncrement is 16
let postIncrement = y++; // postIncrement is 3, y is now 4
console.log(typeof z); // "number"
// Ternary
let age = 20;
let status = age >= 18 ? "adult" : "minor"; // "adult"
// ---------------------------------------------------------------------------------
// 6. Control Flow Statements
// ---------------------------------------------------------------------------------
// Control flow statements determine the order in which code is executed.
// Conditional Statements:
// - `if...else`: Executes code based on a condition.
// - `switch`: Executes code based on the value of an expression.
// if...else
let num = 10;
if (num > 0) {
console.log("Positive");
} else if (num < 0) {
console.log("Negative");
} else {
console.log("Zero");
}
// switch
let day = "Monday";
switch (day) {
case "Monday":
console.log("Start of the week");
break;
case "Friday":
console.log("Almost the weekend");
break;
default:
console.log("Another day");
}
// Looping Statements:
// - `for`: Repeats a block of code a specific number of times.
// - `while`: Repeats a block of code as long as a condition is true.
// - `do...while`: Similar to `while`, but the code block is executed at least once.
// - `for...in`: Loops over properties of an object (not recommended for arrays).
// - `for...of`: Loops over the values of an object (arrays, strings, maps, sets, etc.).
// for
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// while
let i = 0;
while (i < 5) {
console.log(i); // 0, 1, 2, 3, 4
i++;
}
// do...while
let j = 0;
do {
console.log(j); // 0, 1, 2, 3, 4
j++;
} while (j < 5);
// for...in (iterates over object keys)
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key); // "a", "b", "c"
console.log(obj[key]); // Accessing value using the key: 1, 2, 3
}
// for...of (iterates over iterable values)
const arr = [10, 20, 30];
for (const value of arr) {
console.log(value); // 10, 20, 30
}
const str = "hello";
for (const char of str) {
console.log(char); // "h", "e", "l", "l", "o"
}
// Transfer Statements:
// - `break`: Exits a loop or switch statement.
// - `continue`: Skips the current iteration of a loop and continues with the next.
// - `return`: Exits a function and optionally returns a value.
// break
for (let k = 0; k < 10; k++) {
if (k === 5) {
break; // Exit the loop when k is 5
}
console.log(k); // 0, 1, 2, 3, 4
}
// continue
for (let m = 0; m < 5; m++) {
if (m === 2) {
continue; // Skip the iteration when m is 2
}
console.log(m); // 0, 1, 3, 4
}
// return
function add(a, b) {
return a + b; // Exit the function and return the sum
}
let sumResult = add(3, 4); // 7
// ---------------------------------------------------------------------------------
// 7. Arrays
// ---------------------------------------------------------------------------------
// Arrays are ordered collections of values. They can hold elements of any data
// type, including other arrays.
// Declaration and Initialization:
let emptyArray = [];
let numbers = [1, 2, 3, 4, 5];
let mixedArray = [1, "hello", true, { name: "Alice" }];
// Accessing Elements:
// Use square brackets and the index (starting from 0).
console.log(numbers[0]); // 1
console.log(mixedArray[1]); // "hello"
// Modifying Elements:
numbers[2] = 10; // Change the element at index 2
console.log(numbers); // [1, 2, 10, 4, 5]
// Array Length:
console.log(numbers.length); // 5
// Adding Elements:
numbers.push(6); // Add to the end: [1, 2, 10, 4, 5, 6]
numbers.unshift(0); // Add to the beginning: [0, 1, 2, 10, 4, 5, 6]
// Removing Elements:
let lastElement = numbers.pop(); // Remove from the end (returns 6)
let firstElement = numbers.shift(); // Remove from the beginning (returns 0)
console.log(numbers); // [1, 2, 10, 4, 5]
// Other Common Array Methods:
// - `concat()`: Joins arrays.
// - `join()`: Converts elements to a string.
// - `slice()`: Extracts a section into a new array.
// - `splice()`: Adds/removes elements (modifies original).
// - `indexOf()`: Returns first index of an element.
// - `includes()`: Checks if array includes a value.
// - `find()`: Returns first element satisfying a condition.
// - `findIndex()`: Returns index of first element satisfying a condition.
// - `filter()`: Creates new array with elements passing a condition.
// - `map()`: Creates new array by applying function to elements.
// - `forEach()`: Executes function for each element (no return).
// - `reduce()`: Reduces array to a single value.
// - `sort()`: Sorts elements (modifies original).
// - `some()`: Checks if any element passes a test.
// - `every()`: Checks if all elements pass a test.
// - `flat()`: Flattens nested arrays to a depth.
// Examples:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]
let joined = arr1.join("-"); // "1-2-3"
let sliced = arr1.slice(1, 3); // [2, 3] (from index 1 up to, but not including, 3)
// Removes 1 element from index 1, inserts 7 and 8. Returns removed elements: [2].
let spliced = arr1.splice(1, 1, 7, 8); // arr1 is now [1, 7, 8, 3]
console.log(arr1.indexOf(3)); // 3
console.log(arr1.includes(7)); // true
let found = arr1.find(element => element > 2); // 7 (first element greater than 2)
let filtered = arr1.filter(element => element > 2); // [7, 8, 3]
let mapped = arr1.map(element => element * 2); // [2, 14, 16, 6]
arr1.forEach(element => console.log(element)); // Prints each element
// 19 (sum of elements)
let sumArr = arr1.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
let unsorted = [3, 1, 4, 1, 5, 9, 2, 6];
// Sorts alphabetically (for strings) or numerically (with a compare function)
unsorted.sort();
let nested = [1, [2, [3, [4]]]];
let flattened = nested.flat(Infinity); // [1, 2, 3, 4]
// ---------------------------------------------------------------------------------
// 8. Functions
// ---------------------------------------------------------------------------------
// Functions are reusable blocks of code that perform a specific task.
// Function Declaration:
function greet(name) {
console.log(`Hello, ${name}!`);
}
// Function Expression:
const add = function(a, b) {
return a + b;
};
// Arrow Function (ES6):
const multiply = (a, b) => a * b;
// Function Call (Invocation):
greet("World"); // "Hello, World!"
let sumFunc = add(5, 3); // 8
let productFunc = multiply(4, 6); // 24
// Parameters and Arguments:
// - Parameters are the variables listed in the function definition.
// - Arguments are the actual values passed to the function when it's called.
// Default Parameters (ES6):
function greetWithDefault(name = "Guest") {
console.log(`Hello, ${name}!`);
}
greetWithDefault(); // "Hello, Guest!"
greetWithDefault("Alice"); // "Hello, Alice!"
// Rest Parameters (ES6):
// Allows a function to accept an indefinite number of arguments as an array.
function sum(...numbers) {
return numbers.reduce((sum, num) => sum + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// Return Value:
// Functions can return a value using the `return` statement. If no `return`
// statement is present, the function returns `undefined`.
// Scope:
// - Variables declared inside a function are local to that function.
// - `let` and `const` are block-scoped (within `{}` blocks).
// Closures:
// A closure is a function that has access to variables from its outer (enclosing)
// function's scope, even after the outer function has finished executing.
function outerFunction() {
let outerVar = "Hello";
function innerFunction() {
console.log(outerVar); // innerFunction has access to outerVar (closure)
}
return innerFunction;
}
let myClosure = outerFunction();
myClosure(); // "Hello"
// Immediately Invoked Function Expression (IIFE):
// A function that is executed immediately after it's defined. Used to create
// private scope.
(function() {
let privateVar = "This is private";
console.log(privateVar);
})();
// console.log(privateVar); // Error: privateVar is not defined (outside the IIFE)
// Higher-Order Functions:
// Functions that take other functions as arguments or return functions.
function applyOperation(a, b, operation) {
return operation(a, b);
}
let resultHOF = applyOperation(5, 3, add); // 8
let result2HOF = applyOperation(5, 3, multiply); // 15
// Callback Functions:
// Functions passed as arguments to other functions, to be executed later. Common
// in asynchronous operations.
function fetchData(callback) {
setTimeout(() => {
const data = { name: "Example Data" };
callback(data); // Call the callback function with the fetched data
}, 1000);
}
fetchData(data => {
console.log("Received data:", data); // Received data: {name: 'Example Data'}
});
// ---------------------------------------------------------------------------------
// 9. Objects
// ---------------------------------------------------------------------------------
// Objects are collections of key-value pairs. Keys are strings (or Symbols),
// and values can be any data type, including other objects or functions.
// Object Literal Notation:
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
address: {
street: "123 Main St",
city: "Anytown"
},
greet: function() { // Method
console.log(`Hello, my name is ${this.firstName}`);
}
};
// Accessing Properties:
// - Dot notation: `object.property`
// - Bracket notation: `object["property"]` (useful when the property name is dynamic)
console.log(person.firstName); // "John"
console.log(person["lastName"]); // "Doe"
console.log(person.address.city); // "Anytown"
// Modifying Properties:
person.age = 31;
person["lastName"] = "Smith";
// Adding Properties:
person.email = "[email protected]";
// Deleting Properties:
delete person.age;
// Methods:
// Functions that are properties of an object.
person.greet(); // "Hello, my name is John"
// `this` Keyword:
// Inside a method, `this` refers to the object the method belongs to.
// Constructor Functions:
// Used to create multiple objects of the same type.
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.greet = function() {
console.log(`Hello, my name is ${this.firstName}`);
};
}
const person1 = new Person("Alice", "Smith", 25);
const person2 = new Person("Bob", "Jones", 30);
person1.greet(); // "Hello, my name is Alice"
// Prototypes:
// Every JavaScript object has a prototype, which is another object. Objects
// inherit properties and methods from their prototype.
// The `prototype` property of a constructor function is used to add properties
// and methods to all instances created by that constructor.
Person.prototype.getFullName = function() {
return `${this.firstName} ${this.lastName}`;
};
console.log(person1.getFullName()); // "Alice Smith"
// Object.create():
// Creates a new object with the specified prototype object and properties.
const animal = {
makeSound: function() { console.log("Generic animal sound"); }
};
const dog = Object.create(animal);
dog.bark = function() { console.log("Woof!"); };
dog.makeSound(); // "Generic animal sound"
dog.bark(); // "Woof!"
// Object Destructuring:
// A concise way to extract properties from objects into variables.
const { firstName, lastName } = person;
console.log(firstName); // "John"
console.log(lastName); // "Smith"
// Spread Syntax (...):
// Used to copy properties from one object to another, or to merge objects.
const personCopy = { ...person }; // Shallow copy
const mergedObject = { ...person, occupation: "Engineer" };
// Object.keys(), Object.values(), Object.entries():
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));
// ---------------------------------------------------------------------------------
// 10. DOM Manipulation
// ---------------------------------------------------------------------------------
// The Document Object Model (DOM) is a programming interface for HTML and XML
// documents. It represents the page as a tree of nodes, allowing JavaScript to
// access and manipulate the structure, style, and content of the page.
// Accessing Elements:
// - `document.getElementById(id)`: Gets element by ID.
// - `document.getElementsByClassName(className)`: Gets elements by class.
// - `document.getElementsByTagName(tagName)`: Gets elements by tag.
// - `document.querySelector(selector)`: Gets first element matching CSS selector.
// - `document.querySelectorAll(selector)`: Gets all elements matching CSS selector.
// Modifying Elements:
// - `element.textContent`: Gets/sets text content.
// - `element.innerHTML`: Gets/sets HTML content.
// - `element.setAttribute(name, value)`: Sets attribute value.
// - `element.getAttribute(name)`: Gets attribute value.
// - `element.removeAttribute(name)`: Removes attribute.
// - `element.style`: Modifies inline styles.
// - `element.classList`: Manages CSS classes (add/remove/toggle).
// Creating and Appending Elements:
// - `document.createElement(tagName)`: Creates new element.
// - `element.appendChild(childElement)`: Appends child to parent.
// - `element.insertBefore(newElement, referenceElement)`: Inserts new element before reference.
// - `element.removeChild(childElement)`: Removes child element.
// - `element.replaceChild(newChild, oldChild)`: Replaces child element.
// Examples:
// HTML:
// <div id="myDiv" class="container">
// <p>This is a paragraph.</p>
// <ul>
// <li>Item 1</li>
// <li>Item 2</li>
// </ul>
// </div>
// JavaScript:
const myDiv = document.getElementById("myDiv");
const paragraphs = document.getElementsByTagName("p");
const firstParagraph = document.querySelector("p");
const listItems = document.querySelectorAll("li");
// Accessing
console.log(myDiv.textContent); // " This is a paragraph. Item 1 Item 2 "
console.log(paragraphs[0].textContent); // "This is a paragraph."
// Modifying
firstParagraph.textContent = "This is an updated paragraph.";
myDiv.style.backgroundColor = "lightblue";
myDiv.classList.add("highlight");
// Creating and Appending
const newListItem = document.createElement("li");
newListItem.textContent = "Item 3";
const ul = document.querySelector("ul");
ul.appendChild(newListItem);
// Removing
const itemToRemove = listItems[0];
ul.removeChild(itemToRemove);
// ---------------------------------------------------------------------------------
// 11. Events
// ---------------------------------------------------------------------------------
// Events are actions or occurrences that happen in the browser (user interactions,
// page loading, etc.). JavaScript can listen for and respond to these events.
// Event Handling:
// - Inline event handlers (in HTML): `<button onclick="myFunction()">` (not recommended)
// - DOM property event handlers: `element.onclick = function() { ... };`
// - Event listeners: `element.addEventListener(eventType, function, useCapture);` (preferred)
// Common Event Types:
// - Mouse Events: `click`, `dblclick`, `mouseover`, `mouseout`, `mousedown`, `mouseup`, `mousemove`
// - Keyboard Events: `keydown`, `keyup`, `keypress`
// - Form Events: `submit`, `change`, `input`, `focus`, `blur`
// - Window Events: `load`, `resize`, `scroll`, `unload`
// - Touch Events: `touchstart`, `touchmove`, `touchend`, `touchcancel`
// Event Object:
// When an event occurs, an event object is automatically passed to the event
// handler function. This object contains information about the event (type,
// target element, mouse coordinates, key pressed, etc.).
// Event Propagation:
// - Bubbling: The event is first handled by the innermost element and then
// propagates up to the outermost element.
// - Capturing: The event is first handled by the outermost element and then
// propagates down to the innermost element. (less commonly used)
// - `event.stopPropagation()`: Prevents the event from bubbling up or capturing down.
// Preventing Default Behavior:
// - `event.preventDefault()`: Prevents the default action associated with an
// event (e.g., preventing a form submission).
// Examples:
// HTML:
// <button id="myButton">Click Me</button>
// <form id="myForm">
// <input type="text" id="myInput">
// <button type="submit">Submit</button>
// </form>
// JavaScript:
const button = document.getElementById("myButton");
const input = document.getElementById("myInput");
const form = document.getElementById("myForm");
// Event Listener
button.addEventListener("click", function(event) {
console.log("Button clicked!");
console.log("Event type:", event.type); // "click"
console.log("Target element:", event.target); // <button id="myButton">
});
// Keyboard Event
input.addEventListener("keydown", function(event) {
console.log("Key pressed:", event.key);
});
// Form Event (preventing default submission)
form.addEventListener("submit", function(event) {
event.preventDefault(); // Prevent the form from submitting
console.log("Form submitted (but prevented)");
});
// Event Propagation (Bubbling) Example:
// <div id="outer">
// <button id="inner">Inner Button</button>
// </div>
const outer = document.getElementById("outer");
const inner = document.getElementById("inner");
outer.addEventListener("click", function(event) {
console.log("Outer div clicked");
});
inner.addEventListener("click", function(event) {
console.log("Inner button clicked");
// event.stopPropagation(); // Uncomment to stop the bubbling
});
// Clicking "Inner Button
// (Output without stopPropagation: "Inner button clicked", "Outer div clicked")
// (Output with stopPropagation: "Inner button clicked")
// ---------------------------------------------------------------------------------
// 12. Asynchronous JavaScript
// ---------------------------------------------------------------------------------
// Asynchronous JavaScript allows you to execute code without blocking the main
// thread, preventing the user interface from freezing.
// Key Concepts:
// - Callbacks: Functions passed as arguments to other functions, to be executed
// later (often after an asynchronous operation completes).
// - Promises: Objects representing the eventual completion (or failure) of an
// asynchronous operation. They have states (pending, fulfilled, rejected) and
// methods like `.then()` and `.catch()` to handle the results.
// - Async/Await: Syntactic sugar built on top of Promises, making asynchronous
// code look and behave more like synchronous code.
// Common Asynchronous Operations:
// - `setTimeout()`: Executes a function after a specified delay.
// - `setInterval()`: Repeatedly executes a function at a specified interval.
// - Fetch API: Used for making network requests (e.g., fetching data from a server).
// - AJAX (Asynchronous JavaScript and XML): A set of techniques for making
// asynchronous requests to a server (Fetch API is generally preferred now).
// - Event listeners (many events are asynchronous).
// Examples:
// setTimeout
console.log("Before setTimeout");
setTimeout(() => {
console.log("Inside setTimeout (after 2 seconds)");
}, 2000); // 2000 milliseconds = 2 seconds
console.log("After setTimeout");
// Output:
// Before setTimeout
// After setTimeout
// Inside setTimeout (after 2 seconds)
// setInterval
let counter = 0;
const intervalId = setInterval(() => {
console.log("Interval:", counter);
counter++;
if (counter > 3) {
clearInterval(intervalId); // Stop the interval
}
}, 1000);
// Callback Example:
function getData(callback) {
setTimeout(() => {
const data = { message: "This is the data" };
callback(data); // Call the callback with the data
}, 1000);
}
getData(data => {
console.log("Received data:", data); // Received data: {message: 'This is the data'}
});
// Promise Example:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve({ data: "Fetched data!" }); // Resolve with the data
} else {
reject("Error fetching data"); // Reject with an error message
}
}, 1500);
});
}
fetchData()
.then(result => { // .then() handles successful resolution
console.log("Success:", result.data); // Success: Fetched data!
})
.catch(error => { // .catch() handles rejection
console.error("Error:", error);
});
// Async/Await Example:
async function getDataAsync() {
try {
const result = await fetchData(); // Await the Promise resolution
console.log("Async/Await Success:", result.data); // Async/Await Success: Fetched data!
} catch (error) {
console.error("Async/Await Error:", error);
}
}
getDataAsync();
// Fetch API Example:
fetch("https://jsonplaceholder.typicode.com/todos/1") // Example API endpoint
.then(response => {
if (!response.ok) { // Check for HTTP errors
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json(); // Parse the JSON response
})
.then(data => {
console.log("Fetched data:", data); // Fetched data: {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
})
.catch(error => {
console.error("Fetch error:", error);
});
// ---------------------------------------------------------------------------------
// 13. Error Handling
// ---------------------------------------------------------------------------------
// Error handling is crucial for writing robust code. JavaScript provides
// mechanisms to handle errors gracefully and prevent unexpected program crashes.
// `try...catch` Statement:
// - `try`: Encloses the code that might throw an error.
// - `catch`: Handles the error if one occurs within the `try` block.
// - `finally`: (Optional) Executes code regardless of whether an error occurred.
// `throw` Statement:
// - Used to manually throw an error (can be a built-in error object or a custom error).
// Error Object:
// - When an error occurs, a JavaScript Error object is created.
// - Properties:
// - `name`: The type of error (e.g., "Error", "TypeError", "ReferenceError").
// - `message`: A description of the error.
// - `stack`: (Non-standard, but widely supported) The call stack at the time of the error.
// Examples:
try {
// Code that might throw an error
let result = undefinedVariable + 10; // ReferenceError: undefinedVariable is not defined
} catch (error) {
console.error("Error name:", error.name); // Error name: ReferenceError
console.error("Error message:", error.message); // Error message: undefinedVariable is not defined
// console.error("Stack trace:", error.stack);
} finally {
console.log("Finally block executed"); // Finally block executed
}
// Throwing a custom error:
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
try {
let result = divide(10, 0);
} catch (error) {
console.error(error.message); // Division by zero is not allowed
}
// Creating a custom error class:
class ValidationError extends Error {
constructor(message) {
super(message); // Call the parent constructor with the message
this.name = "ValidationError"; // Set the error name
}
}
try {
throw new ValidationError("Invalid input data");
} catch (error) {
if (error instanceof ValidationError) {
console.error("Validation Error:", error.message); // Validation Error: Invalid input data
} else {
console.error("Other Error:", error.message);
}
}
// ---------------------------------------------------------------------------------
// 14. Classes
// ---------------------------------------------------------------------------------
// Classes provide a more structured way to create objects and implement
// inheritance, introduced in ES6 (ECMAScript 2015). They are syntactic sugar
// over JavaScript's existing prototype-based inheritance.
// Class Declaration:
class Animal {
// Constructor: Initializes the object
constructor(name) {
this.name = name;
}
// Method
speak() {
console.log(`${this.name} makes a sound.`);
}
// Static Method (associated with the class, not instances)
static info() {
console.log("This is the Animal class.");
}
}
// Creating an Instance:
const myAnimal = new Animal("Generic Animal");
myAnimal.speak(); // "Generic Animal makes a sound."
Animal.info(); // "This is the Animal class."
// Inheritance:
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call the parent class constructor
this.breed = breed;
}
// Overriding a method
speak() {
console.log(`${this.name} barks!`);
}
// New method specific to Dog
fetch() {
console.log(`${this.name} fetches a ball.`);
}
}
const myDog = new Dog("Buddy", "Golden Retriever");
myDog.speak(); // "Buddy barks!"
myDog.fetch(); // "Buddy fetches a ball."
console.log(myDog.breed); // Golden Retriever
// Getters and Setters:
class Rectangle {
constructor(width, height) {
this._width = width; // Use _ to indicate "private" (convention)
this._height = height;
}
get width() {
return this._width;
}
set width(value) {
if (value > 0) {
this._width = value;
} else {
console.error("Width must be positive.");
}
}
get height() {
return this._height;
}
set height(value) {
if (value > 0) {
this._height = value;
} else {
console.error("Height must be positive");
}
}
get area() {
return this._width * this._height;
}
}
const rect = new Rectangle(5, 10);
console.log(rect.area); // 50
rect.width = 12;
console.log(rect.area); // 120
rect.width = -5; // "Width must be positive."
// ---------------------------------------------------------------------------------
// 15. Iterators and Generators
// ---------------------------------------------------------------------------------
// Iterators:
// Objects that define a sequence and potentially a return value upon its
// termination. They implement the *iterator protocol*, which requires a `next()`
// method that returns an object with `value` and `done` properties.
// Generators:
// Special functions that can be paused and resumed, allowing you to create
// iterators in a more concise way. They use the `function*` syntax and the
// `yield` keyword.
// Examples:
// Custom Iterator:
const myIterator = {
data: [1, 2, 3],
currentIndex: 0,
next() {
if (this.currentIndex < this.data.length) {
return { value: this.data[this.currentIndex++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
console.log(myIterator.next()); // {value: 1, done: false}
console.log(myIterator.next()); // {value: 2, done: false}
console.log(myIterator.next()); // {value: 3, done: false}
console.log(myIterator.next()); // {value: undefined, done: true}
// Making an Object Iterable:
const myIterable = {
data: [4,5,6],
[Symbol.iterator](){
let index = 0;
const self = this;
return {
next(){
if(index < self.data.length){
return {value: self.data[index++], done: false}
}else{
return {value: undefined, done: true}
}
}
}
}
}
for (const value of myIterable) {
console.log(value); // 4, 5, 6
}
// Generator Function:
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = myGenerator();
console.log(gen.next()); // {value: 1, done: false}
console.log(gen.next()); // {value: 2, done: false}
console.log(gen.next()); // {value: 3, done: false}
console.log(gen.next()); // {value: undefined, done: true}
// Generator for Infinite Sequence:
function* infiniteNumbers() {
let n = 0;
while (true) {
yield n++;
}
}
const infiniteGen = infiniteNumbers();
console.log(infiniteGen.next().value); // 0
console.log(infiniteGen.next().value); // 1
console.log(infiniteGen.next().value); // 2
// ... and so on
// Using Generators with `for...of`:
function* iterateArray(arr) {
for (const item of arr) {
yield item;
}
}
const myArray = ["a", "b", "c"];
for (const value of iterateArray(myArray)) {
console.log(value); // "a", "b", "c"
}
// ---------------------------------------------------------------------------------
// 18. Debugging
// ---------------------------------------------------------------------------------
// Debugging is the process of finding and fixing errors in your code.
// Tools and Techniques:
// - Browser Developer Tools: All modern browsers have built-in developer tools
// that provide a powerful debugger.
// - Console: Log messages, inspect variables, execute code.
// - Sources (or Debugger): Set breakpoints, step through code, inspect the call stack.
// - Network: Monitor network requests.
// - Elements (or Inspector): Inspect and modify the DOM and CSS.
// - Performance: Profile the performance of your code.
// - `console.log()`: The simplest way to debug is to log values to the console.
// - `debugger;` statement: Inserts a breakpoint in your code, pausing execution
// in the debugger.
// - Linting: Use a linter (like ESLint) to catch potential errors and enforce
// coding style.
// - Unit Testing: Write unit tests to verify that individual parts of your code
// work as expected.
// Examples:
// Using console.log()
function myFunction(a, b) {
console.log("a:", a);
console.log("b:", b);
return a + b;
}
// Using the debugger statement
function anotherFunction() {
let x = 5;
debugger; // Execution will pause here in the debugger
x = x * 2;
console.log("x:", x);
}