SlideShare a Scribd company logo
Complete JavaScript Notes
1. Introduction to JavaScript
JavaScript is a versatile and powerful programming language primarily known for its
role in web development. It enables interactive and dynamic content on websites,
making them more engaging and user-friendly. Beyond web browsers, JavaScript has
expanded its reach to various other domains, including server-side development with
Node.js, mobile app development with frameworks like React Native, and even
desktop applications.
What is JavaScript?
JavaScript is a high-level, interpreted programming language that conforms to the
ECMAScript specification. It is a multi-paradigm language, supporting event-driven,
functional, and imperative programming styles. Unlike compiled languages,
JavaScript code is executed directly by an interpreter, typically within a web browser's
JavaScript engine or a Node.js runtime environment.
History and Evolution
JavaScript was created in 1995 by Brendan Eich while he was working at Netscape
Communications. Initially named LiveScript, it was quickly renamed JavaScript to
capitalize on the popularity of Java at the time, despite having little to no direct
relation to the Java programming language. The language was standardized under
ECMAScript in 1997, and subsequent versions have introduced significant
enhancements and new features, such as ES6 (ECMAScript 2015), which brought major
improvements like arrow functions, classes, and modules.
Where is JavaScript used?
JavaScript's primary domain remains web development, where it powers the client-
side interactivity of millions of websites. However, its applications have diversified
considerably:
Front-end Web Development: Used with HTML and CSS to create dynamic and
interactive user interfaces. Frameworks and libraries like React, Angular, and
Vue.js are built on JavaScript.
Back-end Web Development: With Node.js, JavaScript can be used to build
scalable and high-performance server-side applications, APIs, and microservices.
Mobile App Development: Frameworks such as React Native and NativeScript
allow developers to build cross-platform mobile applications using JavaScript.
Desktop App Development: Electron and NW.js enable the creation of desktop
applications using web technologies (HTML, CSS, JavaScript).
Game Development: JavaScript can be used to develop browser-based games
and even more complex games with libraries like Phaser.
IoT (Internet of Things): JavaScript can be used to program various IoT devices.
Setting up your development environment
To start writing and running JavaScript code, you primarily need a text editor and a
web browser. For more advanced development, a dedicated Integrated Development
Environment (IDE) and Node.js are recommended.
1. Text Editor/IDE: Popular choices include Visual Studio Code, Sublime Text, Atom,
or WebStorm. These provide features like syntax highlighting, autocompletion,
and debugging tools.
2. Web Browser: Modern web browsers (Chrome, Firefox, Edge, Safari) come with
built-in JavaScript engines and developer tools (console, debugger) that are
essential for testing and debugging client-side JavaScript.
3. Node.js: For server-side JavaScript development and to use JavaScript outside
the browser, install Node.js. It includes the npm (Node Package Manager) which
is crucial for managing project dependencies and running development tools.
2. JavaScript Basics
JavaScript's fundamental building blocks include variables, data types, operators, and
control flow statements. Understanding these concepts is crucial for writing any
JavaScript program.
Variables (var, let, const)
Variables are containers for storing data values. JavaScript provides three keywords to
declare variables:
var : Historically used for variable declaration. var declarations are function-
scoped and are hoisted to the top of their function or global scope. This can lead
to unexpected behavior, especially in loops or conditional blocks.
javascript var x = 10; if (true) { var x = 20; // Same variable x
console.log(x); // 20 } console.log(x); // 20
let : Introduced in ES6 (ECMAScript 2015), let declarations are block-scoped.
This means the variable is only accessible within the block (e.g., if statement,
for loop) where it is defined.
javascript let y = 10; if (true) { let y = 20; // Different variable
y console.log(y); // 20 } console.log(y); // 10
const : Also introduced in ES6, const is used to declare constants. Like let ,
const declarations are block-scoped. Once a const variable is assigned a value,
it cannot be reassigned. However, for objects and arrays declared with const ,
their properties or elements can still be modified.
```javascript const PI = 3.14; // PI = 3.14159; // This would cause an error
const person = { name: "Alice" }; person.name = "Bob"; // This is allowed
console.log(person.name); // Bob ```
Data Types (Primitive and Non-Primitive)
JavaScript has several built-in data types. They are broadly categorized into primitive
and non-primitive (or reference) types.
Primitive Data Types:
String : Represents textual data. Enclosed in single quotes ( '...' ), double
quotes (`
"..." ), or backticks ( `...` for template literals). javascript let name = "John
Doe"; * Number : Represents both integer and floating-point numbers. javascript
let age = 30; let price = 99.99; * Boolean : Represents a logical entity and can
have two values: true or false . javascript let isActive = true; * Undefined :
Represents a variable that has been declared but has not yet been assigned a value.
javascript let city; // city is undefined * Null : Represents the intentional
absence of any object value. It is a primitive value. javascript let car = null; *
Symbol : (ES6) Represents a unique identifier. Used to create unique property keys that
won't clash with other property keys. javascript const id = Symbol('id'); *
BigInt : (ES2020) Represents whole numbers larger than 2^53 - 1, which is the largest
number JavaScript can reliably represent with the Number primitive. javascript
const bigNumber = 1234567890123456789012345678901234567890n;
Non-Primitive (Reference) Data Types:
Object : A collection of key-value pairs. Objects are the most fundamental non-
primitive data type. javascript let person = { firstName: "John",
lastName: "Doe" };
Array : A special type of object used to store ordered collections of data.
javascript let colors = ["red", "green", "blue"];
Function : A block of code designed to perform a particular task. Functions are
also objects in JavaScript. javascript function greet(name) { return
"Hello, " + name; }
Operators (Arithmetic, Assignment, Comparison, Logical, etc.)
Operators are symbols that perform operations on operands (values and variables).
Arithmetic Operators: Perform mathematical calculations.
Operator Description Example
+ Addition x + y
- Subtraction x - y
* Multiplication x * y
/ Division x / y
% Modulus x % y
** Exponentiation x ** y
++ Increment x++ or ++x
-- Decrement x-- or --x
Assignment Operators: Assign values to variables.
Operator Example Same As
= x = y x = y
+= x += y x = x + y
-= x -= y x = x - y
*= x *= y x = x * y
/= x /= y x = x / y
%= x %= y x = x % y
**= x **= y x = x ** y
Comparison Operators: Compare two values and return a boolean result.
Operator Description Example
== Equal to (loose equality) x == y
=== Equal value and type (strict equality) x === y
!= Not equal (loose inequality) x != y
!== Not equal value or type (strict inequality) x !== y
> Greater than x > y
< Less than x < y
>= Greater than or equal to x >= y
<= Less than or equal to x <= y
Logical Operators: Combine conditional statements.
Operator Description Example
&& Logical AND x < 10 && x > 5
|| Logical OR x < 5 || x > 10
! Logical NOT !(x === 5)
Type Conversion (Implicit and Explicit)
JavaScript is a loosely typed language, meaning variables do not have a fixed type.
Values can be converted from one type to another, either implicitly (coercion) or
explicitly.
Implicit Type Conversion (Coercion): JavaScript automatically converts data
types when an operation involves different types.
javascript console.log("5" + 5); // "55" (Number 5 is converted to
String "5") console.log("5" - 5); // 0 (String "5" is converted to
Number 5) console.log(true + 1); // 2 (Boolean true is converted to
Number 1)
Explicit Type Conversion: Developers explicitly convert data types using built-in
functions or methods.
javascript console.log(Number("10")); // 10 console.log(String(100));
// "100" console.log(Boolean(0)); // false
Conditional Statements (if, else if, else, switch)
Conditional statements execute different actions based on different conditions.
if , else if , else :
javascript let hour = 14; if (hour < 12) { console.log("Good
morning!"); } else if (hour < 18) { console.log("Good afternoon!"); }
else { console.log("Good evening!"); }
switch : Used to perform different actions based on different conditions.
javascript let day = "Monday"; switch (day) { case "Monday":
console.log("It's Monday."); break; case "Friday": console.log("It's
Friday!"); break; default: console.log("It's another day."); }
Loops (for, while, do-while, for...in, for...of)
Loops are used to execute a block of code repeatedly.
for loop: Iterates a block of code a number of times.
javascript for (let i = 0; i < 5; i++) { console.log(i); }
while loop: Executes a block of code as long as a specified condition is true.
javascript let i = 0; while (i < 5) { console.log(i); i++; }
do...while loop: Similar to while , but the block of code is executed at least
once before the condition is tested.
javascript let i = 0; do { console.log(i); i++; } while (i < 5);
for...in loop: Iterates over the enumerable properties of an object.
javascript const person = { fname: "John", lname: "Doe", age: 25 };
for (let x in person) { console.log(x + ": " + person[x]); }
for...of loop: (ES6) Iterates over iterable objects (like Arrays, Strings, Maps,
Sets, etc.).
javascript const colors = ["red", "green", "blue"]; for (let color of
colors) { console.log(color); }
3. Functions
Functions are fundamental building blocks in JavaScript. They are reusable blocks of
code that perform a specific task. Functions allow you to organize your code, make it
more modular, and avoid repetition (DRY - Don't Repeat Yourself principle).
Function Declaration and Expression
There are two primary ways to define functions in JavaScript:
Function Declaration (or Function Statement): This is the most common way
to define a function. Function declarations are hoisted, meaning they can be
called before they are defined in the code.
```javascript // Function Declaration function greet(name) { return "Hello, " +
name + "!"; }
console.log(greet("Alice")); // Output: Hello, Alice! ```
Function Expression: A function expression defines a function as part of an
expression, typically assigned to a variable. Function expressions are not hoisted,
so they cannot be called before they are defined.
```javascript // Function Expression const sayHello = function(name) { return
"Hello, " + name + "!"; };
console.log(sayHello("Bob")); // Output: Hello, Bob! //
console.log(anotherGreet("Charlie")); // This would cause an error if called
before definition ```
Arrow Functions
Arrow functions (introduced in ES6) provide a more concise syntax for writing function
expressions. They also behave differently regarding the this keyword (which will be
discussed in a later section).
Basic Syntax:
javascript const add = (a, b) => a + b; console.log(add(5, 3)); //
Output: 8
Single Parameter: Parentheses are optional for a single parameter.
javascript const square = num => num * num; console.log(square(4));
// Output: 16
No Parameters: Empty parentheses are required.
javascript const sayHi = () => "Hi there!"; console.log(sayHi()); //
Output: Hi there!
Block Body: For multiple statements, use curly braces and a return statement.
javascript const calculateArea = (length, width) => { const area =
length * width; return `The area is ${area} square units.`; };
console.log(calculateArea(10, 5)); // Output: The area is 50 square
units.
Parameters and Arguments
Parameters: Named variables listed in the function definition. They act as
placeholders for the values that will be passed into the function.
Arguments: The actual values passed to the function when it is called.
```javascript function multiply(a, b) { // a and b are parameters return a * b; }
console.log(multiply(7, 2)); // 7 and 2 are arguments ```
Return Values
Functions can return a value using the return statement. If no return statement is
specified, or if return; is used without a value, the function implicitly returns
undefined .
function getMax(x, y) {
if (x > y) {
return x;
} else {
return y;
}
}
let result = getMax(15, 8);
console.log(result); // Output: 15
function doNothing() {
// No return statement
}
console.log(doNothing()); // Output: undefined
Scope (Global, Local, Block)
Scope determines the accessibility of variables, objects, and functions in different
parts of your code.
Global Scope: Variables declared outside any function or block have global
scope. They can be accessed from anywhere in the code.
```javascript let globalVar = "I am global";
function accessGlobal() { console.log(globalVar); } accessGlobal(); // Output: I am
global ```
Function (Local) Scope: Variables declared inside a function (using var , let ,
or const ) are function-scoped. They are only accessible within that function.
javascript function localScopeExample() { var localVar = "I am local
(var)"; let anotherLocalVar = "I am local (let)"; const PI = 3.14; //
Also local console.log(localVar); console.log(anotherLocalVar); }
localScopeExample(); // console.log(localVar); // Error: localVar is
not defined
Block Scope: Variables declared with let and const inside a block (e.g., if
statement, for loop, or any {} block) are block-scoped. They are only
accessible within that block.
javascript if (true) { let blockVar = "I am block-scoped";
console.log(blockVar); // Output: I am block-scoped } //
console.log(blockVar); // Error: blockVar is not defined
Closures
A closure is the combination of a function bundled together (enclosed) with references
to its surrounding state (the lexical environment). In simpler terms, a closure gives you
access to an outer function's scope from an inner function, even after the outer
function has finished executing.
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log("Outer Variable: " + outerVariable);
console.log("Inner Variable: " + innerVariable);
};
}
const newFunction = outerFunction("Hello");
newFunction("World");
// Output:
// Outer Variable: Hello
// Inner Variable: World
// Even after outerFunction has returned, innerFunction still has access to
outerVariable
Closures are powerful for creating private variables and functions, and for
implementing patterns like currying and memoization.
Immediately Invoked Function Expressions (IIFE)
An IIFE is a JavaScript function that runs as soon as it is defined. It's a design pattern
that creates a private scope for variables, preventing them from polluting the global
namespace.
(function() {
var privateVar = "I am private";
console.log(privateVar);
})(); // The function is immediately invoked
// console.log(privateVar); // Error: privateVar is not defined
// IIFE with parameters
(function(message) {
console.log(message);
})("This is an IIFE with a parameter.");
IIFEs are commonly used in older JavaScript codebases to encapsulate modules and
prevent variable collisions.
4. Objects and Arrays
Objects and Arrays are fundamental data structures in JavaScript, used for storing
collections of data. They are both types of objects, but serve different purposes and
have distinct characteristics.
Objects (Creation, Properties, Methods)
An object in JavaScript is a standalone entity, with properties and type. Objects are
collections of key-value pairs. The keys (or property names) are strings (or Symbols),
and the values can be any data type, including other objects, functions, or primitive
values.
Creation of Objects:
1. Object Literal (Recommended for simple objects): The simplest way to create
an object.
javascript const person = { firstName: "John", lastName: "Doe", age:
30, isStudent: false, // A method (function as a property) greet:
function() { return `Hello, my name is $`{this.firstName}
`${this.lastName}.`; } };
2. new Object() (Less common):
javascript const car = new Object(); car.make = "Toyota"; car.model =
"Camry";
3. Constructor Function: Used to create multiple objects of the same type.
``javascript function Book(title, author, year) { this.title = title;
this.author = author; this.year = year; this.getSummary = function()
{ return $ {this.title} by ${this.author}, published in ${this.year}.`; }; }
const book1 = new Book("The Hobbit", "J.R.R. Tolkien", 1937);
console.log(book1.getSummary()); ```
4. class Keyword (ES6): Syntactic sugar over constructor functions and
prototypes.
```javascript class Animal { constructor(name, species) { this.name = name;
this.species = species; }
makeSound() {
console.log("Generic animal sound");
}
}
const dog = new Animal("Buddy", "Dog"); dog.makeSound(); ```
Accessing Properties:
Dot Notation (Recommended):
javascript console.log(person.firstName); // "John"
Bracket Notation (Useful for dynamic property names or properties with
special characters):
javascript console.log(person["lastName"]); // "Doe" let prop =
"age"; console.log(person[prop]); // 30
Modifying Properties:
person.age = 31;
person["isStudent"] = true;
console.log(person.age); // 31
console.log(person.isStudent); // true
Adding New Properties:
person.nationality = "American";
console.log(person.nationality); // "American"
Deleting Properties:
delete person.isStudent;
console.log(person.isStudent); // undefined
Methods: Functions stored as object properties.
console.log(person.greet()); // "Hello, my name is John Doe."
Arrays (Creation, Methods, Iteration)
Arrays are ordered collections of values. Each value is called an element, and each
element has a numeric position called an index (starting from 0).
Creation of Arrays:
1. Array Literal (Recommended):
javascript const fruits = ["apple", "banana", "cherry"]; const
numbers = [1, 2, 3, 4, 5]; const mixed = ["text", 123, true, { key:
"value" }];
2. new Array() (Less common):
javascript const emptyArray = new Array(); const fiveElements = new
Array(5); // Creates an array with 5 empty slots const colors = new
Array("red", "green", "blue");
Accessing Elements:
Elements are accessed using their index in bracket notation.
console.log(fruits[0]); // "apple"
console.log(fruits[2]); // "cherry"
console.log(fruits.length); // 3
Modifying Elements:
fruits[1] = "grape";
console.log(fruits); // ["apple", "grape", "cherry"]
Common Array Methods:
JavaScript provides a rich set of built-in methods for manipulating arrays.
Method Description Example
push()
Adds one or more elements to the end of
an array and returns the new length.
arr.push("new")
pop()
Removes the last element from an array
and returns that element.
arr.pop()
shift()
Removes the first element from an array
and returns that element.
arr.shift()
unshift()
Adds one or more elements to the
beginning of an array and returns the new
length.
arr.unshift("first")
splice()
Changes the contents of an array by
removing or replacing existing elements
and/or adding new elements in place.
arr.splice(index,
deleteCount, item1, ...)
slice()
Returns a shallow copy of a portion of an
array into a new array object.
arr.slice(startIndex,
endIndex)
concat() Used to merge two or more arrays. arr1.concat(arr2)
indexOf()
Returns the first index at which a given
element can be found in the array, or -1 if it
is not present.
arr.indexOf("item")
includes()
Determines whether an array includes a
certain value among its entries, returning
true or false as appropriate.
arr.includes("item")
forEach()
Executes a provided function once for each
array element.
arr.forEach(callback)
map()
Creates a new array populated with the
results of calling a provided function on
every element in the calling array.
arr.map(callback)
filter()
Creates a new array with all elements that
pass the test implemented by the provided
function.
arr.filter(callback)
Method Description Example
reduce()
Executes a reducer function (that you
provide) on each element of the array,
resulting in single output value.
arr.reduce(callback,
initialValue)
find()
Returns the value of the first element in
the provided array that satisfies the
provided testing function.
arr.find(callback)
sort()
Sorts the elements of an array in place and
returns the sorted array.
arr.sort()
reverse() Reverses an array in place. arr.reverse()
Iteration over Arrays:
for loop:
javascript for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]); }
forEach() method:
javascript fruits.forEach(function(fruit, index) {
console.log(`$`{index}: `${fruit}`); });
for...of loop (ES6):
javascript for (const fruit of fruits) { console.log(fruit); }
Destructuring (Object and Array)
Destructuring assignment is a special syntax that allows you to unpack values from
arrays, or properties from objects, into distinct variables.
Object Destructuring:
```javascript const person = { name: "Alice", age: 25, city: "New York" }; const {
name, age } = person; console.log(name); // "Alice" console.log(age); // 25
// Renaming variables const { name: personName, city: personCity } = person;
console.log(personName); // "Alice" console.log(personCity); // "New York" ```
Array Destructuring:
```javascript const colors = ["red", "green", "blue"]; const [firstColor,
secondColor] = colors; console.log(firstColor); // "red" console.log(secondColor);
// "green"
// Skipping elements const [,, thirdColor] = colors; console.log(thirdColor); //
"blue"
// With rest operator const [primary, ...restColors] = colors; console.log(primary);
// "red" console.log(restColors); // ["green", "blue"] ```
Spread and Rest Operators
Both the spread ( ... ) and rest ( ... ) operators use the same syntax but serve
different purposes based on where they are used.
Spread Operator ( ... ): Expands an iterable (like an array or string) into
individual elements. Useful for copying arrays, merging arrays, or passing
multiple arguments to a function.
```javascript // Copying an array const originalArray = [1, 2, 3]; const copiedArray
= [...originalArray]; // [1, 2, 3]
// Merging arrays const arr1 = [1, 2]; const arr2 = [3, 4]; const mergedArray =
[...arr1, ...arr2]; // [1, 2, 3, 4]
// Spreading properties in objects (ES2018) const obj1 = { a: 1, b: 2 }; const obj2 = {
c: 3, d: 4 }; const mergedObject = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
// Passing arguments to a function function sum(a, b, c) { return a + b + c; } const
nums = [1, 2, 3]; console.log(sum(...nums)); // 6 ```
Rest Operator ( ... ): Collects multiple elements into an array. Used in function
parameters to handle an indefinite number of arguments, or in destructuring
assignments.
```javascript // In function parameters function collectArgs(firstArg, ...restArgs) {
console.log(firstArg); // "A" console.log(restArgs); // ["B", "C", "D"] }
collectArgs("A", "B", "C", "D");
// In array destructuring (as shown above) const [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1 console.log(tail); // [2, 3, 4] ```
5. Asynchronous JavaScript
JavaScript is a single-threaded language, meaning it can only execute one task at a
time. However, many operations, such as fetching data from a server, reading a file, or
waiting for a user action, can take time. If these operations were synchronous
(blocking), the entire application would freeze until they completed. Asynchronous
programming allows JavaScript to handle these long-running tasks without blocking
the main thread, ensuring a smooth and responsive user experience.
Callbacks
A callback is a function passed as an argument to another function, which is then
invoked inside the outer function to complete some kind of routine or action. This is
the traditional way of handling asynchronous operations in JavaScript.
function fetchData(callback) {
// Simulate a network request
setTimeout(() => {
const data = { message: "Data fetched successfully!" };
callback(null, data); // Pass null for error, and data on success
}, 2000);
}
console.log("Fetching data...");
fetchData((error, data) => {
if (error) {
console.error("Error:", error);
} else {
console.log(data.message);
}
});
console.log("This will be logged before the data is fetched.");
Callback Hell (Pyramid of Doom): When multiple asynchronous operations depend
on each other, you can end up with nested callbacks, which makes the code hard to
read and maintain. This is known as "callback hell."
Promises (States, Chaining, Error Handling)
Promises, introduced in ES6, provide a cleaner and more robust way to handle
asynchronous operations. A Promise is an object representing the eventual
completion (or failure) of an asynchronous operation and its resulting value.
Promise States:
pending : Initial state, neither fulfilled nor rejected.
fulfilled : The operation completed successfully.
rejected : The operation failed.
Creating a Promise:
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation
setTimeout(() => {
const success = true;
if (success) {
resolve("Promise resolved!");
} else {
reject("Promise rejected!");
}
}, 2000);
});
Consuming a Promise:
myPromise
.then(result => {
console.log(result); // "Promise resolved!"
})
.catch(error => {
console.error(error); // "Promise rejected!"
})
.finally(() => {
console.log("Promise finished.");
});
Promise Chaining: Promises can be chained together to handle a sequence of
asynchronous operations.
fetch('https://api.example.com/data')
.then(response => response.json()) // .json() also returns a promise
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
Async/Await
async/await , introduced in ES2017, is syntactic sugar built on top of Promises. It
allows you to write asynchronous code that looks and behaves more like synchronous
code, making it easier to read and reason about.
async function: A function declared with the async keyword automatically
returns a Promise .
await operator: The await operator is used to wait for a Promise to resolve. It
can only be used inside an async function.
async function fetchDataAsync() {
try {
console.log("Fetching data...");
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
fetchDataAsync();
Event Loop
The Event Loop is the mechanism that allows JavaScript to perform non-blocking
asynchronous operations, despite being single-threaded. It continuously checks the
message queue for new messages (tasks) and executes them.
1. Call Stack: Where function calls are pushed and popped.
2. Web APIs (Browser) / C++ APIs (Node.js): Handle asynchronous operations
(e.g., setTimeout , fetch ).
3. Message Queue (or Task Queue): Where callback functions are placed after the
asynchronous operation is complete.
4. Event Loop: When the Call Stack is empty, the Event Loop takes the first message
from the Message Queue and pushes it onto the Call Stack for execution.
This model ensures that the main thread is not blocked by long-running operations,
allowing the user interface to remain responsive.
6. DOM Manipulation
The Document Object Model (DOM) is a programming interface for web documents. It
represents the page structure as a tree of objects, where each object corresponds to a
part of the document, such as an element, attribute, or text. JavaScript can interact
with this DOM tree to dynamically change the content, structure, and style of a web
page.
What is the DOM?
When a web page is loaded, the browser creates a DOM of the page. The DOM is a
platform- and language-neutral interface that allows programs and scripts to
dynamically access and update the content, structure, and style of documents. It
represents the document as nodes and objects.
For example, consider this simple HTML:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<h1 id="main-title">Hello, DOM!</h1>
<p class="intro">This is a paragraph.</p>
<button>Click Me</button>
</body>
</html>
The DOM represents this as a tree structure, where document is the root, html is its
child, and so on.
Selecting Elements
To manipulate elements, you first need to select them. JavaScript provides several
methods for this:
document.getElementById() : Selects a single element by its id attribute.
Returns null if the element is not found.
javascript const titleElement = document.getElementById("main-
title"); console.log(titleElement.textContent); // "Hello, DOM!"
document.getElementsByClassName() : Selects all elements with a specific class
name. Returns an HTMLCollection (live collection).
javascript const introParagraphs =
document.getElementsByClassName("intro");
console.log(introParagraphs[0].textContent); // "This is a
paragraph."
document.getElementsByTagName() : Selects all elements with a specific tag
name. Returns an HTMLCollection.
javascript const allParagraphs = document.getElementsByTagName("p");
console.log(allParagraphs.length); // 1
document.querySelector() : Selects the first element that matches a specified
CSS selector. This is a very versatile method.
javascript const firstParagraph = document.querySelector("p.intro");
console.log(firstParagraph.textContent); // "This is a paragraph."
const button = document.querySelector("button");
document.querySelectorAll() : Selects all elements that match a specified CSS
selector. Returns a NodeList (static collection).
javascript const allElements = document.querySelectorAll("h1, p");
allElements.forEach(el => console.log(el.tagName)); // H1, P
Modifying HTML Content and Attributes
Once you have selected an element, you can modify its content and attributes.
textContent : Gets or sets the text content of an element (ignores HTML tags).
javascript titleElement.textContent = "New Title!";
console.log(titleElement.textContent); // "New Title!"
innerHTML : Gets or sets the HTML content of an element (parses HTML tags).
javascript firstParagraph.innerHTML = "This is a
<strong>bold</strong> paragraph.";
setAttribute() : Sets the value of an attribute on the specified element.
javascript button.setAttribute("id", "myButton");
removeAttribute() : Removes an attribute from an element.
javascript // button.removeAttribute("id");
classList : Provides methods to add, remove, toggle, or check for CSS classes.
javascript button.classList.add("btn-primary");
button.classList.remove("btn-secondary");
button.classList.toggle("active"); // Adds if not present, removes if
present if (button.classList.contains("btn-primary")) {
console.log("Button has btn-primary class."); }
Styling Elements
You can change the inline styles of elements using the style property.
titleElement.style.color = "blue";
titleElement.style.fontSize = "40px";
titleElement.style.backgroundColor = "lightgray";
For more complex styling or when applying multiple styles, it's often better to toggle
CSS classes.
Event Handling
Events are actions or occurrences that happen in the browser, such as a user clicking a
button, a page loading, or a key being pressed. JavaScript allows you to respond to
these events.
addEventListener() : The recommended way to attach event handlers. It allows
multiple handlers for the same event on the same element.
```javascript button.addEventListener("click", function() { alert("Button
clicked!"); });
// You can add multiple listeners button.addEventListener("click", () => {
console.log("Another click handler."); }); ```
Event Object: When an event occurs, an Event object is passed to the event
handler function. This object contains information about the event.
javascript button.addEventListener("click", (event) => {
console.log("Event type:", event.type); console.log("Target
element:", event.target); });
Common Events:
click : When an element is clicked.
mouseover , mouseout : When the mouse pointer enters/leaves an element.
keydown , keyup : When a key is pressed/released.
submit : When a form is submitted.
load : When a page or an image has finished loading.
change : When the value of an input element changes.
7. ES6+ Features
ECMAScript 2015 (ES6) marked a significant turning point in JavaScript development,
introducing a plethora of new features that greatly improved the language's
expressiveness, readability, and capabilities. Subsequent annual releases (ES2016,
ES2017, etc.) have continued to add valuable enhancements. Here are some of the
most impactful ES6+ features:
Template Literals
Template literals (also known as template strings) provide a more flexible and
readable way to create strings, especially when they involve variables or expressions.
They are enclosed by backticks ( ` ) instead of single or double quotes.
Multi-line Strings: Easily create strings that span multiple lines without using
n .
javascript const multiLine = ` This is a string that spans multiple
lines. `; console.log(multiLine);
Expression Interpolation: Embed expressions directly within the string using
${expression} .
``javascript const name = "World"; const greeting = Hello, ${name}!`;
console.log(greeting); // "Hello, World!"
const a = 10; const b = 5; console.log( The sum of $ and ${b} is ${a + b}. ); //
"The sum of 10 and 5 is 15." ```
Classes
Classes, introduced in ES6, are a syntactic sugar over JavaScript's existing prototype-
based inheritance. They provide a cleaner and more familiar object-oriented syntax for
creating objects and handling inheritance.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is $`{this.name} and I am `${this.age} years
old.`;
}
}
const john = new Person("John Doe", 30);
console.log(john.greet()); // "Hello, my name is John Doe and I am 30 years
old."
// Inheritance
class Student extends Person {
constructor(name, age, studentId) {
super(name, age); // Call the parent class constructor
this.studentId = studentId;
}
study() {
return `$`{this.name} (ID: `${this.studentId}) is studying.`;
}
}
const alice = new Student("Alice Smith", 20, "S12345");
console.log(alice.greet()); // "Hello, my name is Alice Smith and I am 20 years
old."
console.log(alice.study()); // "Alice Smith (ID: S12345) is studying."
Modules (Import/Export)
ES6 modules provide a standardized way to organize JavaScript code into separate
files, making it easier to manage dependencies, improve reusability, and prevent
global namespace pollution. Modules use export to make variables, functions, or
classes available to other files, and import to bring them into the current file.
math.js (Exporting module):
// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export default function subtract(a, b) {
return a - b;
}
app.js (Importing module):
// app.js
import { PI, add } from './math.js'; // Named imports
import subtractAlias from './math.js'; // Default import (can be renamed)
console.log(PI); // 3.14159
console.log(add(5, 2)); // 7
console.log(subtractAlias(10, 3)); // 7
// Import all as an object
import * as MathFunctions from './math.js';
console.log(MathFunctions.PI);
Iterators and Generators
Iterators: An object is an iterator when it implements the next() method, which
returns an object with two properties: value (the next value in the sequence)
and done (a boolean indicating if the sequence has finished).
Generators: Generator functions are a special type of function that can be
paused and resumed, allowing them to produce a sequence of values over time.
They are defined using function* and use the yield keyword to pause
execution and return a value.
```javascript function* idGenerator() { let id = 1; while (true) { yield id++; } }
const gen = idGenerator(); console.log(gen.next().value); // 1
console.log(gen.next().value); // 2 console.log(gen.next().value); // 3 ```
Map and Set
ES6 introduced new built-in objects for storing collections of data, offering advantages
over plain objects and arrays in certain scenarios.
Map : A collection of key-value pairs where keys can be of any data type (unlike
plain objects where keys are limited to strings or Symbols). Map maintains the
insertion order of elements.
```javascript const myMap = new Map(); myMap.set("name", "Alice");
myMap.set(1, "one"); myMap.set(true, "boolean");
console.log(myMap.get("name")); // "Alice" console.log(myMap.has(1)); // true
myMap.delete("name"); console.log(myMap.size); // 2
// Iterating over a Map for (const [key, value] of myMap) { console.log( $ :
${value} ); } ```
Set : A collection of unique values. Duplicate values are automatically ignored.
Set maintains the insertion order of elements.
```javascript const mySet = new Set(); mySet.add(1); mySet.add("hello");
mySet.add(1); // This will be ignored
console.log(mySet.has("hello")); // true mySet.delete(1); console.log(mySet.size);
// 1
// Iterating over a Set for (const item of mySet) { console.log(item); }
// Convert array to Set to get unique values const numbers = [1, 2, 2, 3, 4, 4, 5];
const uniqueNumbers = [...new Set(numbers)]; console.log(uniqueNumbers); //
[1, 2, 3, 4, 5] ```
8. Advanced Concepts
Beyond the foundational elements and modern features, JavaScript encompasses
several advanced concepts that are crucial for writing robust, efficient, and
maintainable code. Understanding these concepts helps in debugging complex issues
and mastering the language.
this Keyword
The this keyword in JavaScript is one of the most misunderstood concepts. Its value
is determined by how a function is called, not where it is defined. The this context
can change dynamically.
Global Context: In the global execution context (outside of any function), this
refers to the global object ( window in browsers, global in Node.js).
javascript console.log(this === window); // true (in browser)
Function Context (Simple Function Call): In a regular function call, this also
refers to the global object (or undefined in strict mode).
javascript function showThis() { console.log(this); } showThis(); //
window object (non-strict), undefined (strict)
Method Context: When a function is called as a method of an object, this refers
to the object that owns the method.
javascript const person = { name: "Alice", greet: function() {
console.log(`Hello, my name is ${this.name}`); } }; person.greet();
// "Hello, my name is Alice"
Constructor Context: When a function is used as a constructor with the new
keyword, this refers to the newly created instance of the object.
javascript function Car(make) { this.make = make; } const myCar = new
Car("Toyota"); console.log(myCar.make); // "Toyota"
Explicit Binding ( call , apply , bind ):
call() : Invokes the function with a specified this value and arguments
provided individually.
apply() : Invokes the function with a specified this value and arguments
provided as an array.
bind() : Returns a new function, allowing you to permanently set the this
context.
```javascript const anotherPerson = { name: "Bob" };
function sayName() { console.log(this.name); }
sayName.call(anotherPerson); // "Bob" sayName.apply(anotherPerson); // "Bob"
const boundSayName = sayName.bind(anotherPerson); boundSayName(); //
"Bob" ```
Arrow Functions and this : Arrow functions do not have their own this
context. They inherit this from their lexical (enclosing) scope. This makes them
very useful in callbacks where you want to preserve the this context of the
surrounding code.
javascript const user = { name: "Charlie", logMessages: function() {
setTimeout(() => { console.log(`Hello from ${this.name}`); // 'this'
refers to 'user' }, 1000); } }; user.logMessages(); // "Hello from
Charlie" (after 1 second)
Prototypes and Prototypal Inheritance
JavaScript is a prototype-based language, meaning that objects can inherit properties
and methods directly from other objects. Every JavaScript object has a prototype,
which is another object that it inherits properties and methods from. The prototype
chain is how inheritance works in JavaScript.
__proto__ and [[Prototype]] : Every object has an internal [[Prototype]]
property, which points to its prototype object. This is often exposed via the
__proto__ property (though Object.getPrototypeOf() is the standard way to
access it).
prototype property of functions: Functions in JavaScript also have a
prototype property. When a function is used as a constructor (with new ), the
prototype property of the constructor function becomes the [[Prototype]] of
the newly created object.
```javascript function Vehicle(make) { this.make = make; }
Vehicle.prototype.getMake = function() { return this.make; };
const car = new Vehicle("Honda"); console.log(car.getMake()); // "Honda"
console.log(car.proto === Vehicle.prototype); // true
console.log(Object.getPrototypeOf(car) === Vehicle.prototype); // true ```
Prototype Chain: When you try to access a property or method on an object,
JavaScript first looks for it directly on the object. If it doesn't find it, it then looks
on the object's prototype, then on the prototype's prototype, and so on, until it
reaches null (the end of the chain).
javascript // Example of prototype chain console.log(car.toString());
// Inherited from Object.prototype
console.log(car.__proto__.__proto__ === Object.prototype); // true
Hoisting
Hoisting is a JavaScript mechanism where variable and function declarations are
moved to the top of their containing scope during the compilation phase, before code
execution. This means you can use variables and functions before they are declared in
your code.
Function Hoisting: Function declarations are fully hoisted, meaning both the
function name and its definition are moved to the top. So, you can call a function
before its declaration.
```javascript hoistedFunction(); // "Hello from hoisted function!"
function hoistedFunction() { console.log("Hello from hoisted function!"); } ```
Variable Hoisting ( var ): Variables declared with var are hoisted, but only their
declaration is hoisted, not their initialization. This means they are initialized with
undefined .
javascript console.log(hoistedVar); // undefined var hoistedVar = "I
am hoisted"; console.log(hoistedVar); // "I am hoisted"
let and const (Temporal Dead Zone): Variables declared with let and
const are also hoisted, but they are not initialized. They are in a "Temporal Dead
Zone" (TDZ) from the beginning of the block until their declaration is processed.
Accessing them before declaration will result in a ReferenceError .
javascript // console.log(tdzVar); // ReferenceError: Cannot access
'tdzVar' before initialization let tdzVar = "I am in TDZ";
Event Delegation
Event delegation is a technique where you attach a single event listener to a parent
element, instead of attaching multiple event listeners to individual child elements.
This single listener then listens for events bubbling up from its children. It's
particularly useful for dynamically added elements or a large number of similar
elements.
Benefits: * Performance: Reduces the number of event listeners, saving memory and
improving performance. * Dynamic Elements: Automatically handles events for
elements added to the DOM after the initial page load. * Simpler Code: Less code to
write and maintain.
<ul id="myList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
const myList = document.getElementById("myList");
myList.addEventListener("click", function(event) {
// Check if the clicked element is an LI
if (event.target.tagName === "LI") {
console.log("Clicked on:", event.target.textContent);
event.target.style.color = "red";
}
});
// Dynamically add a new item
const newItem = document.createElement("li");
newItem.textContent = "Item 4";
myList.appendChild(newItem);
// Clicking on Item 4 will also work due to event delegation
Error Handling (try...catch...finally)
Error handling is crucial for creating robust applications. JavaScript provides the
try...catch...finally statement to handle runtime errors gracefully.
try block: Contains the code that might throw an error.
catch block: Contains the code to be executed if an error occurs in the try
block. It receives the error object as an argument.
finally block: Contains code that will always be executed, regardless of
whether an error occurred or not.
function divide(a, b) {
try {
if (b === 0) {
throw new Error("Division by zero is not allowed.");
}
return a / b;
} catch (error) {
console.error("An error occurred:", error.message);
return NaN; // Return Not a Number on error
} finally {
console.log("Division operation attempted.");
}
}
console.log(divide(10, 2)); // Output: 5, then "Division operation attempted."
console.log(divide(10, 0)); // Output: "An error occurred: Division by zero is
not allowed.", then NaN, then "Division operation attempted."
9. Modern JavaScript Development
Modern JavaScript development involves a rich ecosystem of tools and practices that
streamline the development process, improve code quality, and enhance
performance. These tools often work together to transform your source code into
optimized, production-ready applications.
Introduction to npm
npm (Node Package Manager) is the default package manager for Node.js and the
world's largest software registry. It allows developers to share and reuse code, making
it incredibly easy to manage project dependencies and automate development tasks.
Installing npm: npm is installed automatically when you install Node.js.
package.json : This file is at the heart of any npm project. It stores metadata
about the project (name, version, description) and lists all its dependencies
( dependencies for production, devDependencies for development-only tools).
json { "name": "my-js-project", "version": "1.0.0", "description": "A
simple JavaScript project", "main": "index.js", "scripts": { "start":
"node index.js", "test": "echo "Error: no test specified" && exit
1" }, "keywords": [], "author": "Manus AI", "license": "ISC",
"dependencies": { "axios": "^1.6.0" }, "devDependencies": { "eslint":
"^8.56.0" } }
Common npm Commands:
npm init : Initializes a new package.json file.
npm install : Installs all dependencies listed in package.json .
npm install <package-name> : Installs a specific package as a production
dependency.
npm install <package-name> --save-dev or npm install <package-
name> -D : Installs a specific package as a development dependency.
npm uninstall <package-name> : Uninstalls a package.
npm update : Updates packages to their latest compatible versions.
npm run <script-name> : Executes a script defined in the scripts section
of package.json .
Transpilers (Babel)
JavaScript is constantly evolving, with new features being added regularly. However,
not all browsers or Node.js environments support the latest features immediately. A
transpiler (like Babel) converts modern JavaScript code (e.g., ES6+) into an older,
backward-compatible version of JavaScript (e.g., ES5) that can run in a wider range of
environments.
How Babel Works: Babel takes your source code, parses it into an Abstract
Syntax Tree (AST), transforms the AST based on configured plugins and presets,
and then generates new code from the transformed AST.
Presets: Collections of plugins that support a particular set of JavaScript
features (e.g., @babel/preset-env for all modern JavaScript features).
``javascript // ES6+ source code const greet = (name) => Hello,
${name}!`;
// Transpiled ES5 code (by Babel) var greet = function greet(name) { return "Hello,
" + name + "!"; }; ```
Bundlers (Webpack, Parcel)
As JavaScript applications grow, they often consist of many modules and assets (CSS,
images, fonts). Bundlers are tools that combine these separate modules and assets
into a single (or a few) optimized bundles for deployment. This reduces the number of
HTTP requests a browser needs to make, improving load times.
Webpack: A highly configurable and powerful module bundler. It can handle
various asset types through loaders and plugins.
Parcel: A zero-configuration bundler that aims for a faster and easier
development experience.
Key functions of bundlers: * Module Resolution: Understands import and require
statements to build a dependency graph. * Transpilation: Integrates with transpilers
like Babel to convert modern JavaScript. * Minification: Removes unnecessary
characters (whitespace, comments) from code to reduce file size. * Code Splitting:
Divides code into smaller chunks that can be loaded on demand, improving initial load
performance. * Asset Management: Can process and optimize other assets like CSS,
images, and fonts.
Linting (ESLint)
Linting is the process of analyzing source code to flag programming errors, bugs,
stylistic errors, and suspicious constructs. Linters help enforce coding standards and
identify potential problems early in the development cycle.
ESLint: The most popular JavaScript linter. It is highly configurable and allows
developers to define their own rules or use popular style guides (e.g., Airbnb,
Standard).
Benefits of Linting: * Code Quality: Catches common errors and anti-patterns. *
Consistency: Ensures a consistent coding style across a team or project. * Early
Detection: Identifies issues before they become harder to debug runtime errors. *
Improved Readability: Consistent formatting and adherence to best practices make
code easier to read and understand.
Example ESLint rule:
// Bad (ESLint would flag this)
var x = 10;
// Good
const x = 10;
These tools collectively form the backbone of a modern JavaScript development
workflow, enabling developers to build complex, high-quality, and performant
applications efficiently.
10. Best Practices and Tips
Writing good JavaScript code goes beyond just knowing the syntax and features.
Adhering to best practices, optimizing for performance, and understanding debugging
techniques are crucial for building maintainable, scalable, and robust applications.
Clean Code Principles
Clean code is code that is easy to read, understand, and modify. Following these
principles improves collaboration and reduces technical debt.
Meaningful Names: Use descriptive names for variables, functions, and classes
that clearly indicate their purpose. Avoid single-letter names or abbreviations
unless they are universally understood (e.g., i for loop counters).
```javascript // Bad let d = new Date(); let val = calculate(x, y);
// Good let currentDate = new Date(); let totalAmount =
calculateTotalPrice(itemPrice, quantity); ```
Small Functions: Functions should do one thing and do it well. Keep functions
short and focused, ideally no more than 20-30 lines of code.
Avoid Global Variables: Minimize the use of global variables to prevent naming
collisions and make code more modular. Use modules, closures, or IIFEs to
encapsulate variables.
Comments: Write comments that explain why the code does something, not
what it does (the code itself should be self-explanatory). Remove commented-
out code.
Consistency: Maintain a consistent coding style (indentation, naming
conventions, semicolon usage) across your entire codebase. Linters like ESLint
can help enforce this.
DRY (Don't Repeat Yourself): Avoid duplicating code. If you find yourself writing
the same logic multiple times, extract it into a reusable function or module.
Performance Optimization
Optimizing JavaScript code ensures that your applications run smoothly and
efficiently, providing a better user experience.
Minimize DOM Manipulation: DOM operations are expensive. Batch changes,
use document fragments, or update innerHTML once instead of multiple times.
Avoid Layout Thrashing: Repeatedly reading and writing to the DOM can cause
the browser to recalculate layout multiple times. Read all necessary layout
properties first, then perform all writes.
Optimize Loops: For large arrays, prefer for loops over forEach or map if
performance is critical, as native loops can be faster. Cache array.length in
for loops.
javascript // Good for (let i = 0, len = arr.length; i < len; i++) {
// ... }
Debouncing and Throttling: For events that fire frequently (e.g., resize ,
scroll , mousemove , input ), use debouncing or throttling to limit the rate at
which event handlers are executed.
Lazy Loading: Load resources (images, components, modules) only when they
are needed, reducing initial load time.
Use const and let : Prefer const and let over var to improve scope
management and prevent accidental reassignments, which can sometimes lead
to minor performance benefits due to better optimization by JavaScript engines.
Debugging Techniques
Debugging is an essential skill for every developer. Modern browsers provide powerful
developer tools to help you find and fix issues.
console.log() : The simplest and most common debugging tool. Use
console.log() , console.warn() , console.error() , console.table() ,
console.dir() to inspect values and program flow.
Browser Developer Tools:
Elements Tab: Inspect and modify HTML and CSS.
Console Tab: View logs, errors, and execute JavaScript code.
Sources Tab: Set breakpoints, step through code, inspect variables, and
modify code on the fly.
Network Tab: Monitor network requests and responses.
Performance Tab: Analyze runtime performance.
Memory Tab: Profile memory usage.
Breakpoints: Pause code execution at specific lines to inspect the state of
variables and the call stack.
debugger keyword: Insert debugger; into your code to programmatically set a
breakpoint. When the developer tools are open, execution will pause at this
point.
Error Messages: Pay close attention to error messages in the console. They often
provide valuable clues about the type and location of the problem.
Common Pitfalls and How to Avoid Them
Loose Equality ( == ) vs. Strict Equality ( === ): Always use === (strict equality)
to compare values, as == performs type coercion, which can lead to unexpected
results.
javascript console.log(0 == false); // true console.log(0 === false);
// false console.log("5" == 5); // true console.log("5" === 5); //
false
Floating Point Inaccuracy: JavaScript numbers are 64-bit floating-point. This
can lead to precision issues with decimal numbers. Avoid direct comparison of
floating-point numbers.
javascript console.log(0.1 + 0.2 === 0.3); // false
this Context Issues: As discussed, this can be tricky. Be mindful of how
functions are called and use arrow functions or bind / call / apply to control
this when necessary.
Asynchronous Code Complexity: Callback hell, unhandled promises, and race
conditions are common. Use Promises and async/await to manage
asynchronous flow effectively.
Modifying Arrays While Iterating: Avoid adding or removing elements from an
array while iterating over it with for...of or forEach , as this can lead to
skipped elements or infinite loops. Iterate over a copy or use methods like
filter or map to create new arrays.
Global Scope Pollution: Declare variables within the narrowest possible scope
to avoid unintended side effects and conflicts.
By understanding and applying these best practices, you can write more efficient,
readable, and maintainable JavaScript code, leading to more robust and successful
applications.

More Related Content

PDF
Basics of JavaScript
Bala Narayanan
 
PPTX
Unit - 4 all script are here Javascript.pptx
kushwahanitesh592
 
PPTX
Java script.pptx v
22x026
 
PDF
JavaScript Foundations Day1
Troy Miles
 
PPTX
javascript client side scripting la.pptx
lekhacce
 
PPTX
Learning space presentation1 learn Java script
engmk83
 
PDF
1608687-JavaScript+in+Hindi+GLA.pdf
cocid7
 
DOCX
Unit 2.5
Abhishek Kesharwani
 
Basics of JavaScript
Bala Narayanan
 
Unit - 4 all script are here Javascript.pptx
kushwahanitesh592
 
Java script.pptx v
22x026
 
JavaScript Foundations Day1
Troy Miles
 
javascript client side scripting la.pptx
lekhacce
 
Learning space presentation1 learn Java script
engmk83
 
1608687-JavaScript+in+Hindi+GLA.pdf
cocid7
 

Similar to Complete JavaScript Notes: From Basics to Advanced Concepts.pdf (20)

PDF
Javascript - Tutorial
adelaticleanu
 
PPTX
javascript
Kaya Ota
 
PPT
13665449.ppt
JP Chicano
 
PPT
data-types-operators-datatypes-operators.ppt
Gagan Rana
 
PPTX
Javascript
Prashant Kumar
 
PPT
chap04.ppt
Varsha Uchagaonkar
 
PDF
JavaScript for impatient programmers.pdf
JoaqunFerrariIlusus
 
PPT
Java Script
Sarvan15
 
PDF
Java Script
Sarvan15
 
PDF
JavaScript Programming
Sehwan Noh
 
PPT
JavaScript ppt for introduction of javascripta
nehatanveer5765
 
PDF
Javascript
20261A05H0SRIKAKULAS
 
PPT
Presentation JavaScript Introduction Data Types Variables Control Structure
SripathiRavi1
 
PPTX
js.pptx
SuhaibKhan62
 
PPTX
JavaScript Lecture notes.pptx
NishaRohit6
 
PPT
Javascript
Manav Prasad
 
PDF
Java script summary
maamir farooq
 
PDF
javascriptPresentation.pdf
wildcat9335
 
PDF
JavaScript Getting Started
Hazem Hagrass
 
PDF
8 introduction to_java_script
Vijay Kalyan
 
Javascript - Tutorial
adelaticleanu
 
javascript
Kaya Ota
 
13665449.ppt
JP Chicano
 
data-types-operators-datatypes-operators.ppt
Gagan Rana
 
Javascript
Prashant Kumar
 
chap04.ppt
Varsha Uchagaonkar
 
JavaScript for impatient programmers.pdf
JoaqunFerrariIlusus
 
Java Script
Sarvan15
 
Java Script
Sarvan15
 
JavaScript Programming
Sehwan Noh
 
JavaScript ppt for introduction of javascripta
nehatanveer5765
 
Javascript
20261A05H0SRIKAKULAS
 
Presentation JavaScript Introduction Data Types Variables Control Structure
SripathiRavi1
 
js.pptx
SuhaibKhan62
 
JavaScript Lecture notes.pptx
NishaRohit6
 
Javascript
Manav Prasad
 
Java script summary
maamir farooq
 
javascriptPresentation.pdf
wildcat9335
 
JavaScript Getting Started
Hazem Hagrass
 
8 introduction to_java_script
Vijay Kalyan
 
Ad

Recently uploaded (20)

PDF
This slide provides an overview Technology
mineshkharadi333
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PDF
Building High-Performance Oracle Teams: Strategic Staffing for Database Manag...
SMACT Works
 
PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PPTX
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
PPTX
Stamford - Community User Group Leaders_ Agentblazer Status, AI Sustainabilit...
Amol Dixit
 
PDF
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
PDF
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
PDF
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
PDF
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
PDF
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
PDF
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
PDF
Why Your AI & Cybersecurity Hiring Still Misses the Mark in 2025
Virtual Employee Pvt. Ltd.
 
PPT
Coupa-Kickoff-Meeting-Template presentai
annapureddyn
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
PPTX
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
This slide provides an overview Technology
mineshkharadi333
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
Building High-Performance Oracle Teams: Strategic Staffing for Database Manag...
SMACT Works
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
Stamford - Community User Group Leaders_ Agentblazer Status, AI Sustainabilit...
Amol Dixit
 
A Day in the Life of Location Data - Turning Where into How.pdf
Precisely
 
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
Why Your AI & Cybersecurity Hiring Still Misses the Mark in 2025
Virtual Employee Pvt. Ltd.
 
Coupa-Kickoff-Meeting-Template presentai
annapureddyn
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
The-Ethical-Hackers-Imperative-Safeguarding-the-Digital-Frontier.pptx
sujalchauhan1305
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
Ad

Complete JavaScript Notes: From Basics to Advanced Concepts.pdf

  • 1. Complete JavaScript Notes 1. Introduction to JavaScript JavaScript is a versatile and powerful programming language primarily known for its role in web development. It enables interactive and dynamic content on websites, making them more engaging and user-friendly. Beyond web browsers, JavaScript has expanded its reach to various other domains, including server-side development with Node.js, mobile app development with frameworks like React Native, and even desktop applications. What is JavaScript? JavaScript is a high-level, interpreted programming language that conforms to the ECMAScript specification. It is a multi-paradigm language, supporting event-driven, functional, and imperative programming styles. Unlike compiled languages, JavaScript code is executed directly by an interpreter, typically within a web browser's JavaScript engine or a Node.js runtime environment. History and Evolution JavaScript was created in 1995 by Brendan Eich while he was working at Netscape Communications. Initially named LiveScript, it was quickly renamed JavaScript to capitalize on the popularity of Java at the time, despite having little to no direct relation to the Java programming language. The language was standardized under ECMAScript in 1997, and subsequent versions have introduced significant enhancements and new features, such as ES6 (ECMAScript 2015), which brought major improvements like arrow functions, classes, and modules. Where is JavaScript used? JavaScript's primary domain remains web development, where it powers the client- side interactivity of millions of websites. However, its applications have diversified considerably:
  • 2. Front-end Web Development: Used with HTML and CSS to create dynamic and interactive user interfaces. Frameworks and libraries like React, Angular, and Vue.js are built on JavaScript. Back-end Web Development: With Node.js, JavaScript can be used to build scalable and high-performance server-side applications, APIs, and microservices. Mobile App Development: Frameworks such as React Native and NativeScript allow developers to build cross-platform mobile applications using JavaScript. Desktop App Development: Electron and NW.js enable the creation of desktop applications using web technologies (HTML, CSS, JavaScript). Game Development: JavaScript can be used to develop browser-based games and even more complex games with libraries like Phaser. IoT (Internet of Things): JavaScript can be used to program various IoT devices. Setting up your development environment To start writing and running JavaScript code, you primarily need a text editor and a web browser. For more advanced development, a dedicated Integrated Development Environment (IDE) and Node.js are recommended. 1. Text Editor/IDE: Popular choices include Visual Studio Code, Sublime Text, Atom, or WebStorm. These provide features like syntax highlighting, autocompletion, and debugging tools. 2. Web Browser: Modern web browsers (Chrome, Firefox, Edge, Safari) come with built-in JavaScript engines and developer tools (console, debugger) that are essential for testing and debugging client-side JavaScript. 3. Node.js: For server-side JavaScript development and to use JavaScript outside the browser, install Node.js. It includes the npm (Node Package Manager) which is crucial for managing project dependencies and running development tools. 2. JavaScript Basics JavaScript's fundamental building blocks include variables, data types, operators, and control flow statements. Understanding these concepts is crucial for writing any JavaScript program.
  • 3. Variables (var, let, const) Variables are containers for storing data values. JavaScript provides three keywords to declare variables: var : Historically used for variable declaration. var declarations are function- scoped and are hoisted to the top of their function or global scope. This can lead to unexpected behavior, especially in loops or conditional blocks. javascript var x = 10; if (true) { var x = 20; // Same variable x console.log(x); // 20 } console.log(x); // 20 let : Introduced in ES6 (ECMAScript 2015), let declarations are block-scoped. This means the variable is only accessible within the block (e.g., if statement, for loop) where it is defined. javascript let y = 10; if (true) { let y = 20; // Different variable y console.log(y); // 20 } console.log(y); // 10 const : Also introduced in ES6, const is used to declare constants. Like let , const declarations are block-scoped. Once a const variable is assigned a value, it cannot be reassigned. However, for objects and arrays declared with const , their properties or elements can still be modified. ```javascript const PI = 3.14; // PI = 3.14159; // This would cause an error const person = { name: "Alice" }; person.name = "Bob"; // This is allowed console.log(person.name); // Bob ``` Data Types (Primitive and Non-Primitive) JavaScript has several built-in data types. They are broadly categorized into primitive and non-primitive (or reference) types. Primitive Data Types: String : Represents textual data. Enclosed in single quotes ( '...' ), double quotes (` "..." ), or backticks ( `...` for template literals). javascript let name = "John Doe"; * Number : Represents both integer and floating-point numbers. javascript
  • 4. let age = 30; let price = 99.99; * Boolean : Represents a logical entity and can have two values: true or false . javascript let isActive = true; * Undefined : Represents a variable that has been declared but has not yet been assigned a value. javascript let city; // city is undefined * Null : Represents the intentional absence of any object value. It is a primitive value. javascript let car = null; * Symbol : (ES6) Represents a unique identifier. Used to create unique property keys that won't clash with other property keys. javascript const id = Symbol('id'); * BigInt : (ES2020) Represents whole numbers larger than 2^53 - 1, which is the largest number JavaScript can reliably represent with the Number primitive. javascript const bigNumber = 1234567890123456789012345678901234567890n; Non-Primitive (Reference) Data Types: Object : A collection of key-value pairs. Objects are the most fundamental non- primitive data type. javascript let person = { firstName: "John", lastName: "Doe" }; Array : A special type of object used to store ordered collections of data. javascript let colors = ["red", "green", "blue"]; Function : A block of code designed to perform a particular task. Functions are also objects in JavaScript. javascript function greet(name) { return "Hello, " + name; } Operators (Arithmetic, Assignment, Comparison, Logical, etc.) Operators are symbols that perform operations on operands (values and variables). Arithmetic Operators: Perform mathematical calculations.
  • 5. Operator Description Example + Addition x + y - Subtraction x - y * Multiplication x * y / Division x / y % Modulus x % y ** Exponentiation x ** y ++ Increment x++ or ++x -- Decrement x-- or --x Assignment Operators: Assign values to variables. Operator Example Same As = x = y x = y += x += y x = x + y -= x -= y x = x - y *= x *= y x = x * y /= x /= y x = x / y %= x %= y x = x % y **= x **= y x = x ** y Comparison Operators: Compare two values and return a boolean result.
  • 6. Operator Description Example == Equal to (loose equality) x == y === Equal value and type (strict equality) x === y != Not equal (loose inequality) x != y !== Not equal value or type (strict inequality) x !== y > Greater than x > y < Less than x < y >= Greater than or equal to x >= y <= Less than or equal to x <= y Logical Operators: Combine conditional statements. Operator Description Example && Logical AND x < 10 && x > 5 || Logical OR x < 5 || x > 10 ! Logical NOT !(x === 5) Type Conversion (Implicit and Explicit) JavaScript is a loosely typed language, meaning variables do not have a fixed type. Values can be converted from one type to another, either implicitly (coercion) or explicitly. Implicit Type Conversion (Coercion): JavaScript automatically converts data types when an operation involves different types. javascript console.log("5" + 5); // "55" (Number 5 is converted to String "5") console.log("5" - 5); // 0 (String "5" is converted to Number 5) console.log(true + 1); // 2 (Boolean true is converted to Number 1)
  • 7. Explicit Type Conversion: Developers explicitly convert data types using built-in functions or methods. javascript console.log(Number("10")); // 10 console.log(String(100)); // "100" console.log(Boolean(0)); // false Conditional Statements (if, else if, else, switch) Conditional statements execute different actions based on different conditions. if , else if , else : javascript let hour = 14; if (hour < 12) { console.log("Good morning!"); } else if (hour < 18) { console.log("Good afternoon!"); } else { console.log("Good evening!"); } switch : Used to perform different actions based on different conditions. javascript let day = "Monday"; switch (day) { case "Monday": console.log("It's Monday."); break; case "Friday": console.log("It's Friday!"); break; default: console.log("It's another day."); } Loops (for, while, do-while, for...in, for...of) Loops are used to execute a block of code repeatedly. for loop: Iterates a block of code a number of times. javascript for (let i = 0; i < 5; i++) { console.log(i); } while loop: Executes a block of code as long as a specified condition is true. javascript let i = 0; while (i < 5) { console.log(i); i++; } do...while loop: Similar to while , but the block of code is executed at least once before the condition is tested. javascript let i = 0; do { console.log(i); i++; } while (i < 5); for...in loop: Iterates over the enumerable properties of an object.
  • 8. javascript const person = { fname: "John", lname: "Doe", age: 25 }; for (let x in person) { console.log(x + ": " + person[x]); } for...of loop: (ES6) Iterates over iterable objects (like Arrays, Strings, Maps, Sets, etc.). javascript const colors = ["red", "green", "blue"]; for (let color of colors) { console.log(color); } 3. Functions Functions are fundamental building blocks in JavaScript. They are reusable blocks of code that perform a specific task. Functions allow you to organize your code, make it more modular, and avoid repetition (DRY - Don't Repeat Yourself principle). Function Declaration and Expression There are two primary ways to define functions in JavaScript: Function Declaration (or Function Statement): This is the most common way to define a function. Function declarations are hoisted, meaning they can be called before they are defined in the code. ```javascript // Function Declaration function greet(name) { return "Hello, " + name + "!"; } console.log(greet("Alice")); // Output: Hello, Alice! ``` Function Expression: A function expression defines a function as part of an expression, typically assigned to a variable. Function expressions are not hoisted, so they cannot be called before they are defined. ```javascript // Function Expression const sayHello = function(name) { return "Hello, " + name + "!"; }; console.log(sayHello("Bob")); // Output: Hello, Bob! // console.log(anotherGreet("Charlie")); // This would cause an error if called before definition ```
  • 9. Arrow Functions Arrow functions (introduced in ES6) provide a more concise syntax for writing function expressions. They also behave differently regarding the this keyword (which will be discussed in a later section). Basic Syntax: javascript const add = (a, b) => a + b; console.log(add(5, 3)); // Output: 8 Single Parameter: Parentheses are optional for a single parameter. javascript const square = num => num * num; console.log(square(4)); // Output: 16 No Parameters: Empty parentheses are required. javascript const sayHi = () => "Hi there!"; console.log(sayHi()); // Output: Hi there! Block Body: For multiple statements, use curly braces and a return statement. javascript const calculateArea = (length, width) => { const area = length * width; return `The area is ${area} square units.`; }; console.log(calculateArea(10, 5)); // Output: The area is 50 square units. Parameters and Arguments Parameters: Named variables listed in the function definition. They act as placeholders for the values that will be passed into the function. Arguments: The actual values passed to the function when it is called. ```javascript function multiply(a, b) { // a and b are parameters return a * b; } console.log(multiply(7, 2)); // 7 and 2 are arguments ```
  • 10. Return Values Functions can return a value using the return statement. If no return statement is specified, or if return; is used without a value, the function implicitly returns undefined . function getMax(x, y) { if (x > y) { return x; } else { return y; } } let result = getMax(15, 8); console.log(result); // Output: 15 function doNothing() { // No return statement } console.log(doNothing()); // Output: undefined Scope (Global, Local, Block) Scope determines the accessibility of variables, objects, and functions in different parts of your code. Global Scope: Variables declared outside any function or block have global scope. They can be accessed from anywhere in the code. ```javascript let globalVar = "I am global"; function accessGlobal() { console.log(globalVar); } accessGlobal(); // Output: I am global ``` Function (Local) Scope: Variables declared inside a function (using var , let , or const ) are function-scoped. They are only accessible within that function. javascript function localScopeExample() { var localVar = "I am local (var)"; let anotherLocalVar = "I am local (let)"; const PI = 3.14; // Also local console.log(localVar); console.log(anotherLocalVar); } localScopeExample(); // console.log(localVar); // Error: localVar is not defined
  • 11. Block Scope: Variables declared with let and const inside a block (e.g., if statement, for loop, or any {} block) are block-scoped. They are only accessible within that block. javascript if (true) { let blockVar = "I am block-scoped"; console.log(blockVar); // Output: I am block-scoped } // console.log(blockVar); // Error: blockVar is not defined Closures A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In simpler terms, a closure gives you access to an outer function's scope from an inner function, even after the outer function has finished executing. function outerFunction(outerVariable) { return function innerFunction(innerVariable) { console.log("Outer Variable: " + outerVariable); console.log("Inner Variable: " + innerVariable); }; } const newFunction = outerFunction("Hello"); newFunction("World"); // Output: // Outer Variable: Hello // Inner Variable: World // Even after outerFunction has returned, innerFunction still has access to outerVariable Closures are powerful for creating private variables and functions, and for implementing patterns like currying and memoization. Immediately Invoked Function Expressions (IIFE) An IIFE is a JavaScript function that runs as soon as it is defined. It's a design pattern that creates a private scope for variables, preventing them from polluting the global namespace.
  • 12. (function() { var privateVar = "I am private"; console.log(privateVar); })(); // The function is immediately invoked // console.log(privateVar); // Error: privateVar is not defined // IIFE with parameters (function(message) { console.log(message); })("This is an IIFE with a parameter."); IIFEs are commonly used in older JavaScript codebases to encapsulate modules and prevent variable collisions. 4. Objects and Arrays Objects and Arrays are fundamental data structures in JavaScript, used for storing collections of data. They are both types of objects, but serve different purposes and have distinct characteristics. Objects (Creation, Properties, Methods) An object in JavaScript is a standalone entity, with properties and type. Objects are collections of key-value pairs. The keys (or property names) are strings (or Symbols), and the values can be any data type, including other objects, functions, or primitive values. Creation of Objects: 1. Object Literal (Recommended for simple objects): The simplest way to create an object. javascript const person = { firstName: "John", lastName: "Doe", age: 30, isStudent: false, // A method (function as a property) greet: function() { return `Hello, my name is $`{this.firstName} `${this.lastName}.`; } }; 2. new Object() (Less common): javascript const car = new Object(); car.make = "Toyota"; car.model = "Camry";
  • 13. 3. Constructor Function: Used to create multiple objects of the same type. ``javascript function Book(title, author, year) { this.title = title; this.author = author; this.year = year; this.getSummary = function() { return $ {this.title} by ${this.author}, published in ${this.year}.`; }; } const book1 = new Book("The Hobbit", "J.R.R. Tolkien", 1937); console.log(book1.getSummary()); ``` 4. class Keyword (ES6): Syntactic sugar over constructor functions and prototypes. ```javascript class Animal { constructor(name, species) { this.name = name; this.species = species; } makeSound() { console.log("Generic animal sound"); } } const dog = new Animal("Buddy", "Dog"); dog.makeSound(); ``` Accessing Properties: Dot Notation (Recommended): javascript console.log(person.firstName); // "John" Bracket Notation (Useful for dynamic property names or properties with special characters): javascript console.log(person["lastName"]); // "Doe" let prop = "age"; console.log(person[prop]); // 30 Modifying Properties: person.age = 31; person["isStudent"] = true; console.log(person.age); // 31 console.log(person.isStudent); // true Adding New Properties:
  • 14. person.nationality = "American"; console.log(person.nationality); // "American" Deleting Properties: delete person.isStudent; console.log(person.isStudent); // undefined Methods: Functions stored as object properties. console.log(person.greet()); // "Hello, my name is John Doe." Arrays (Creation, Methods, Iteration) Arrays are ordered collections of values. Each value is called an element, and each element has a numeric position called an index (starting from 0). Creation of Arrays: 1. Array Literal (Recommended): javascript const fruits = ["apple", "banana", "cherry"]; const numbers = [1, 2, 3, 4, 5]; const mixed = ["text", 123, true, { key: "value" }]; 2. new Array() (Less common): javascript const emptyArray = new Array(); const fiveElements = new Array(5); // Creates an array with 5 empty slots const colors = new Array("red", "green", "blue"); Accessing Elements: Elements are accessed using their index in bracket notation. console.log(fruits[0]); // "apple" console.log(fruits[2]); // "cherry" console.log(fruits.length); // 3 Modifying Elements:
  • 15. fruits[1] = "grape"; console.log(fruits); // ["apple", "grape", "cherry"] Common Array Methods: JavaScript provides a rich set of built-in methods for manipulating arrays.
  • 16. Method Description Example push() Adds one or more elements to the end of an array and returns the new length. arr.push("new") pop() Removes the last element from an array and returns that element. arr.pop() shift() Removes the first element from an array and returns that element. arr.shift() unshift() Adds one or more elements to the beginning of an array and returns the new length. arr.unshift("first") splice() Changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. arr.splice(index, deleteCount, item1, ...) slice() Returns a shallow copy of a portion of an array into a new array object. arr.slice(startIndex, endIndex) concat() Used to merge two or more arrays. arr1.concat(arr2) indexOf() Returns the first index at which a given element can be found in the array, or -1 if it is not present. arr.indexOf("item") includes() Determines whether an array includes a certain value among its entries, returning true or false as appropriate. arr.includes("item") forEach() Executes a provided function once for each array element. arr.forEach(callback) map() Creates a new array populated with the results of calling a provided function on every element in the calling array. arr.map(callback) filter() Creates a new array with all elements that pass the test implemented by the provided function. arr.filter(callback)
  • 17. Method Description Example reduce() Executes a reducer function (that you provide) on each element of the array, resulting in single output value. arr.reduce(callback, initialValue) find() Returns the value of the first element in the provided array that satisfies the provided testing function. arr.find(callback) sort() Sorts the elements of an array in place and returns the sorted array. arr.sort() reverse() Reverses an array in place. arr.reverse() Iteration over Arrays: for loop: javascript for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]); } forEach() method: javascript fruits.forEach(function(fruit, index) { console.log(`$`{index}: `${fruit}`); }); for...of loop (ES6): javascript for (const fruit of fruits) { console.log(fruit); } Destructuring (Object and Array) Destructuring assignment is a special syntax that allows you to unpack values from arrays, or properties from objects, into distinct variables. Object Destructuring: ```javascript const person = { name: "Alice", age: 25, city: "New York" }; const { name, age } = person; console.log(name); // "Alice" console.log(age); // 25
  • 18. // Renaming variables const { name: personName, city: personCity } = person; console.log(personName); // "Alice" console.log(personCity); // "New York" ``` Array Destructuring: ```javascript const colors = ["red", "green", "blue"]; const [firstColor, secondColor] = colors; console.log(firstColor); // "red" console.log(secondColor); // "green" // Skipping elements const [,, thirdColor] = colors; console.log(thirdColor); // "blue" // With rest operator const [primary, ...restColors] = colors; console.log(primary); // "red" console.log(restColors); // ["green", "blue"] ``` Spread and Rest Operators Both the spread ( ... ) and rest ( ... ) operators use the same syntax but serve different purposes based on where they are used. Spread Operator ( ... ): Expands an iterable (like an array or string) into individual elements. Useful for copying arrays, merging arrays, or passing multiple arguments to a function. ```javascript // Copying an array const originalArray = [1, 2, 3]; const copiedArray = [...originalArray]; // [1, 2, 3] // Merging arrays const arr1 = [1, 2]; const arr2 = [3, 4]; const mergedArray = [...arr1, ...arr2]; // [1, 2, 3, 4] // Spreading properties in objects (ES2018) const obj1 = { a: 1, b: 2 }; const obj2 = { c: 3, d: 4 }; const mergedObject = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 } // Passing arguments to a function function sum(a, b, c) { return a + b + c; } const nums = [1, 2, 3]; console.log(sum(...nums)); // 6 ``` Rest Operator ( ... ): Collects multiple elements into an array. Used in function parameters to handle an indefinite number of arguments, or in destructuring assignments. ```javascript // In function parameters function collectArgs(firstArg, ...restArgs) { console.log(firstArg); // "A" console.log(restArgs); // ["B", "C", "D"] }
  • 19. collectArgs("A", "B", "C", "D"); // In array destructuring (as shown above) const [head, ...tail] = [1, 2, 3, 4]; console.log(head); // 1 console.log(tail); // [2, 3, 4] ``` 5. Asynchronous JavaScript JavaScript is a single-threaded language, meaning it can only execute one task at a time. However, many operations, such as fetching data from a server, reading a file, or waiting for a user action, can take time. If these operations were synchronous (blocking), the entire application would freeze until they completed. Asynchronous programming allows JavaScript to handle these long-running tasks without blocking the main thread, ensuring a smooth and responsive user experience. Callbacks A callback is a function passed as an argument to another function, which is then invoked inside the outer function to complete some kind of routine or action. This is the traditional way of handling asynchronous operations in JavaScript. function fetchData(callback) { // Simulate a network request setTimeout(() => { const data = { message: "Data fetched successfully!" }; callback(null, data); // Pass null for error, and data on success }, 2000); } console.log("Fetching data..."); fetchData((error, data) => { if (error) { console.error("Error:", error); } else { console.log(data.message); } }); console.log("This will be logged before the data is fetched."); Callback Hell (Pyramid of Doom): When multiple asynchronous operations depend on each other, you can end up with nested callbacks, which makes the code hard to read and maintain. This is known as "callback hell."
  • 20. Promises (States, Chaining, Error Handling) Promises, introduced in ES6, provide a cleaner and more robust way to handle asynchronous operations. A Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. Promise States: pending : Initial state, neither fulfilled nor rejected. fulfilled : The operation completed successfully. rejected : The operation failed. Creating a Promise: const myPromise = new Promise((resolve, reject) => { // Asynchronous operation setTimeout(() => { const success = true; if (success) { resolve("Promise resolved!"); } else { reject("Promise rejected!"); } }, 2000); }); Consuming a Promise: myPromise .then(result => { console.log(result); // "Promise resolved!" }) .catch(error => { console.error(error); // "Promise rejected!" }) .finally(() => { console.log("Promise finished."); }); Promise Chaining: Promises can be chained together to handle a sequence of asynchronous operations.
  • 21. fetch('https://api.example.com/data') .then(response => response.json()) // .json() also returns a promise .then(data => { console.log(data); }) .catch(error => { console.error('Error fetching data:', error); }); Async/Await async/await , introduced in ES2017, is syntactic sugar built on top of Promises. It allows you to write asynchronous code that looks and behaves more like synchronous code, making it easier to read and reason about. async function: A function declared with the async keyword automatically returns a Promise . await operator: The await operator is used to wait for a Promise to resolve. It can only be used inside an async function. async function fetchDataAsync() { try { console.log("Fetching data..."); const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('Error:', error); } } fetchDataAsync(); Event Loop The Event Loop is the mechanism that allows JavaScript to perform non-blocking asynchronous operations, despite being single-threaded. It continuously checks the message queue for new messages (tasks) and executes them. 1. Call Stack: Where function calls are pushed and popped. 2. Web APIs (Browser) / C++ APIs (Node.js): Handle asynchronous operations (e.g., setTimeout , fetch ).
  • 22. 3. Message Queue (or Task Queue): Where callback functions are placed after the asynchronous operation is complete. 4. Event Loop: When the Call Stack is empty, the Event Loop takes the first message from the Message Queue and pushes it onto the Call Stack for execution. This model ensures that the main thread is not blocked by long-running operations, allowing the user interface to remain responsive. 6. DOM Manipulation The Document Object Model (DOM) is a programming interface for web documents. It represents the page structure as a tree of objects, where each object corresponds to a part of the document, such as an element, attribute, or text. JavaScript can interact with this DOM tree to dynamically change the content, structure, and style of a web page. What is the DOM? When a web page is loaded, the browser creates a DOM of the page. The DOM is a platform- and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of documents. It represents the document as nodes and objects. For example, consider this simple HTML: <!DOCTYPE html> <html> <head> <title>My Page</title> </head> <body> <h1 id="main-title">Hello, DOM!</h1> <p class="intro">This is a paragraph.</p> <button>Click Me</button> </body> </html> The DOM represents this as a tree structure, where document is the root, html is its child, and so on.
  • 23. Selecting Elements To manipulate elements, you first need to select them. JavaScript provides several methods for this: document.getElementById() : Selects a single element by its id attribute. Returns null if the element is not found. javascript const titleElement = document.getElementById("main- title"); console.log(titleElement.textContent); // "Hello, DOM!" document.getElementsByClassName() : Selects all elements with a specific class name. Returns an HTMLCollection (live collection). javascript const introParagraphs = document.getElementsByClassName("intro"); console.log(introParagraphs[0].textContent); // "This is a paragraph." document.getElementsByTagName() : Selects all elements with a specific tag name. Returns an HTMLCollection. javascript const allParagraphs = document.getElementsByTagName("p"); console.log(allParagraphs.length); // 1 document.querySelector() : Selects the first element that matches a specified CSS selector. This is a very versatile method. javascript const firstParagraph = document.querySelector("p.intro"); console.log(firstParagraph.textContent); // "This is a paragraph." const button = document.querySelector("button"); document.querySelectorAll() : Selects all elements that match a specified CSS selector. Returns a NodeList (static collection). javascript const allElements = document.querySelectorAll("h1, p"); allElements.forEach(el => console.log(el.tagName)); // H1, P
  • 24. Modifying HTML Content and Attributes Once you have selected an element, you can modify its content and attributes. textContent : Gets or sets the text content of an element (ignores HTML tags). javascript titleElement.textContent = "New Title!"; console.log(titleElement.textContent); // "New Title!" innerHTML : Gets or sets the HTML content of an element (parses HTML tags). javascript firstParagraph.innerHTML = "This is a <strong>bold</strong> paragraph."; setAttribute() : Sets the value of an attribute on the specified element. javascript button.setAttribute("id", "myButton"); removeAttribute() : Removes an attribute from an element. javascript // button.removeAttribute("id"); classList : Provides methods to add, remove, toggle, or check for CSS classes. javascript button.classList.add("btn-primary"); button.classList.remove("btn-secondary"); button.classList.toggle("active"); // Adds if not present, removes if present if (button.classList.contains("btn-primary")) { console.log("Button has btn-primary class."); } Styling Elements You can change the inline styles of elements using the style property. titleElement.style.color = "blue"; titleElement.style.fontSize = "40px"; titleElement.style.backgroundColor = "lightgray"; For more complex styling or when applying multiple styles, it's often better to toggle CSS classes.
  • 25. Event Handling Events are actions or occurrences that happen in the browser, such as a user clicking a button, a page loading, or a key being pressed. JavaScript allows you to respond to these events. addEventListener() : The recommended way to attach event handlers. It allows multiple handlers for the same event on the same element. ```javascript button.addEventListener("click", function() { alert("Button clicked!"); }); // You can add multiple listeners button.addEventListener("click", () => { console.log("Another click handler."); }); ``` Event Object: When an event occurs, an Event object is passed to the event handler function. This object contains information about the event. javascript button.addEventListener("click", (event) => { console.log("Event type:", event.type); console.log("Target element:", event.target); }); Common Events: click : When an element is clicked. mouseover , mouseout : When the mouse pointer enters/leaves an element. keydown , keyup : When a key is pressed/released. submit : When a form is submitted. load : When a page or an image has finished loading. change : When the value of an input element changes. 7. ES6+ Features ECMAScript 2015 (ES6) marked a significant turning point in JavaScript development, introducing a plethora of new features that greatly improved the language's expressiveness, readability, and capabilities. Subsequent annual releases (ES2016,
  • 26. ES2017, etc.) have continued to add valuable enhancements. Here are some of the most impactful ES6+ features: Template Literals Template literals (also known as template strings) provide a more flexible and readable way to create strings, especially when they involve variables or expressions. They are enclosed by backticks ( ` ) instead of single or double quotes. Multi-line Strings: Easily create strings that span multiple lines without using n . javascript const multiLine = ` This is a string that spans multiple lines. `; console.log(multiLine); Expression Interpolation: Embed expressions directly within the string using ${expression} . ``javascript const name = "World"; const greeting = Hello, ${name}!`; console.log(greeting); // "Hello, World!" const a = 10; const b = 5; console.log( The sum of $ and ${b} is ${a + b}. ); // "The sum of 10 and 5 is 15." ``` Classes Classes, introduced in ES6, are a syntactic sugar over JavaScript's existing prototype- based inheritance. They provide a cleaner and more familiar object-oriented syntax for creating objects and handling inheritance.
  • 27. class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { return `Hello, my name is $`{this.name} and I am `${this.age} years old.`; } } const john = new Person("John Doe", 30); console.log(john.greet()); // "Hello, my name is John Doe and I am 30 years old." // Inheritance class Student extends Person { constructor(name, age, studentId) { super(name, age); // Call the parent class constructor this.studentId = studentId; } study() { return `$`{this.name} (ID: `${this.studentId}) is studying.`; } } const alice = new Student("Alice Smith", 20, "S12345"); console.log(alice.greet()); // "Hello, my name is Alice Smith and I am 20 years old." console.log(alice.study()); // "Alice Smith (ID: S12345) is studying." Modules (Import/Export) ES6 modules provide a standardized way to organize JavaScript code into separate files, making it easier to manage dependencies, improve reusability, and prevent global namespace pollution. Modules use export to make variables, functions, or classes available to other files, and import to bring them into the current file. math.js (Exporting module): // math.js export const PI = 3.14159; export function add(a, b) { return a + b; } export default function subtract(a, b) { return a - b; }
  • 28. app.js (Importing module): // app.js import { PI, add } from './math.js'; // Named imports import subtractAlias from './math.js'; // Default import (can be renamed) console.log(PI); // 3.14159 console.log(add(5, 2)); // 7 console.log(subtractAlias(10, 3)); // 7 // Import all as an object import * as MathFunctions from './math.js'; console.log(MathFunctions.PI); Iterators and Generators Iterators: An object is an iterator when it implements the next() method, which returns an object with two properties: value (the next value in the sequence) and done (a boolean indicating if the sequence has finished). Generators: Generator functions are a special type of function that can be paused and resumed, allowing them to produce a sequence of values over time. They are defined using function* and use the yield keyword to pause execution and return a value. ```javascript function* idGenerator() { let id = 1; while (true) { yield id++; } } const gen = idGenerator(); console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 console.log(gen.next().value); // 3 ``` Map and Set ES6 introduced new built-in objects for storing collections of data, offering advantages over plain objects and arrays in certain scenarios. Map : A collection of key-value pairs where keys can be of any data type (unlike plain objects where keys are limited to strings or Symbols). Map maintains the insertion order of elements. ```javascript const myMap = new Map(); myMap.set("name", "Alice"); myMap.set(1, "one"); myMap.set(true, "boolean");
  • 29. console.log(myMap.get("name")); // "Alice" console.log(myMap.has(1)); // true myMap.delete("name"); console.log(myMap.size); // 2 // Iterating over a Map for (const [key, value] of myMap) { console.log( $ : ${value} ); } ``` Set : A collection of unique values. Duplicate values are automatically ignored. Set maintains the insertion order of elements. ```javascript const mySet = new Set(); mySet.add(1); mySet.add("hello"); mySet.add(1); // This will be ignored console.log(mySet.has("hello")); // true mySet.delete(1); console.log(mySet.size); // 1 // Iterating over a Set for (const item of mySet) { console.log(item); } // Convert array to Set to get unique values const numbers = [1, 2, 2, 3, 4, 4, 5]; const uniqueNumbers = [...new Set(numbers)]; console.log(uniqueNumbers); // [1, 2, 3, 4, 5] ``` 8. Advanced Concepts Beyond the foundational elements and modern features, JavaScript encompasses several advanced concepts that are crucial for writing robust, efficient, and maintainable code. Understanding these concepts helps in debugging complex issues and mastering the language. this Keyword The this keyword in JavaScript is one of the most misunderstood concepts. Its value is determined by how a function is called, not where it is defined. The this context can change dynamically. Global Context: In the global execution context (outside of any function), this refers to the global object ( window in browsers, global in Node.js). javascript console.log(this === window); // true (in browser)
  • 30. Function Context (Simple Function Call): In a regular function call, this also refers to the global object (or undefined in strict mode). javascript function showThis() { console.log(this); } showThis(); // window object (non-strict), undefined (strict) Method Context: When a function is called as a method of an object, this refers to the object that owns the method. javascript const person = { name: "Alice", greet: function() { console.log(`Hello, my name is ${this.name}`); } }; person.greet(); // "Hello, my name is Alice" Constructor Context: When a function is used as a constructor with the new keyword, this refers to the newly created instance of the object. javascript function Car(make) { this.make = make; } const myCar = new Car("Toyota"); console.log(myCar.make); // "Toyota" Explicit Binding ( call , apply , bind ): call() : Invokes the function with a specified this value and arguments provided individually. apply() : Invokes the function with a specified this value and arguments provided as an array. bind() : Returns a new function, allowing you to permanently set the this context. ```javascript const anotherPerson = { name: "Bob" }; function sayName() { console.log(this.name); } sayName.call(anotherPerson); // "Bob" sayName.apply(anotherPerson); // "Bob" const boundSayName = sayName.bind(anotherPerson); boundSayName(); // "Bob" ``` Arrow Functions and this : Arrow functions do not have their own this context. They inherit this from their lexical (enclosing) scope. This makes them
  • 31. very useful in callbacks where you want to preserve the this context of the surrounding code. javascript const user = { name: "Charlie", logMessages: function() { setTimeout(() => { console.log(`Hello from ${this.name}`); // 'this' refers to 'user' }, 1000); } }; user.logMessages(); // "Hello from Charlie" (after 1 second) Prototypes and Prototypal Inheritance JavaScript is a prototype-based language, meaning that objects can inherit properties and methods directly from other objects. Every JavaScript object has a prototype, which is another object that it inherits properties and methods from. The prototype chain is how inheritance works in JavaScript. __proto__ and [[Prototype]] : Every object has an internal [[Prototype]] property, which points to its prototype object. This is often exposed via the __proto__ property (though Object.getPrototypeOf() is the standard way to access it). prototype property of functions: Functions in JavaScript also have a prototype property. When a function is used as a constructor (with new ), the prototype property of the constructor function becomes the [[Prototype]] of the newly created object. ```javascript function Vehicle(make) { this.make = make; } Vehicle.prototype.getMake = function() { return this.make; }; const car = new Vehicle("Honda"); console.log(car.getMake()); // "Honda" console.log(car.proto === Vehicle.prototype); // true console.log(Object.getPrototypeOf(car) === Vehicle.prototype); // true ``` Prototype Chain: When you try to access a property or method on an object, JavaScript first looks for it directly on the object. If it doesn't find it, it then looks on the object's prototype, then on the prototype's prototype, and so on, until it reaches null (the end of the chain). javascript // Example of prototype chain console.log(car.toString()); // Inherited from Object.prototype
  • 32. console.log(car.__proto__.__proto__ === Object.prototype); // true Hoisting Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase, before code execution. This means you can use variables and functions before they are declared in your code. Function Hoisting: Function declarations are fully hoisted, meaning both the function name and its definition are moved to the top. So, you can call a function before its declaration. ```javascript hoistedFunction(); // "Hello from hoisted function!" function hoistedFunction() { console.log("Hello from hoisted function!"); } ``` Variable Hoisting ( var ): Variables declared with var are hoisted, but only their declaration is hoisted, not their initialization. This means they are initialized with undefined . javascript console.log(hoistedVar); // undefined var hoistedVar = "I am hoisted"; console.log(hoistedVar); // "I am hoisted" let and const (Temporal Dead Zone): Variables declared with let and const are also hoisted, but they are not initialized. They are in a "Temporal Dead Zone" (TDZ) from the beginning of the block until their declaration is processed. Accessing them before declaration will result in a ReferenceError . javascript // console.log(tdzVar); // ReferenceError: Cannot access 'tdzVar' before initialization let tdzVar = "I am in TDZ"; Event Delegation Event delegation is a technique where you attach a single event listener to a parent element, instead of attaching multiple event listeners to individual child elements. This single listener then listens for events bubbling up from its children. It's particularly useful for dynamically added elements or a large number of similar elements.
  • 33. Benefits: * Performance: Reduces the number of event listeners, saving memory and improving performance. * Dynamic Elements: Automatically handles events for elements added to the DOM after the initial page load. * Simpler Code: Less code to write and maintain. <ul id="myList"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> const myList = document.getElementById("myList"); myList.addEventListener("click", function(event) { // Check if the clicked element is an LI if (event.target.tagName === "LI") { console.log("Clicked on:", event.target.textContent); event.target.style.color = "red"; } }); // Dynamically add a new item const newItem = document.createElement("li"); newItem.textContent = "Item 4"; myList.appendChild(newItem); // Clicking on Item 4 will also work due to event delegation Error Handling (try...catch...finally) Error handling is crucial for creating robust applications. JavaScript provides the try...catch...finally statement to handle runtime errors gracefully. try block: Contains the code that might throw an error. catch block: Contains the code to be executed if an error occurs in the try block. It receives the error object as an argument. finally block: Contains code that will always be executed, regardless of whether an error occurred or not.
  • 34. function divide(a, b) { try { if (b === 0) { throw new Error("Division by zero is not allowed."); } return a / b; } catch (error) { console.error("An error occurred:", error.message); return NaN; // Return Not a Number on error } finally { console.log("Division operation attempted."); } } console.log(divide(10, 2)); // Output: 5, then "Division operation attempted." console.log(divide(10, 0)); // Output: "An error occurred: Division by zero is not allowed.", then NaN, then "Division operation attempted." 9. Modern JavaScript Development Modern JavaScript development involves a rich ecosystem of tools and practices that streamline the development process, improve code quality, and enhance performance. These tools often work together to transform your source code into optimized, production-ready applications. Introduction to npm npm (Node Package Manager) is the default package manager for Node.js and the world's largest software registry. It allows developers to share and reuse code, making it incredibly easy to manage project dependencies and automate development tasks. Installing npm: npm is installed automatically when you install Node.js. package.json : This file is at the heart of any npm project. It stores metadata about the project (name, version, description) and lists all its dependencies ( dependencies for production, devDependencies for development-only tools). json { "name": "my-js-project", "version": "1.0.0", "description": "A simple JavaScript project", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "Manus AI", "license": "ISC", "dependencies": { "axios": "^1.6.0" }, "devDependencies": { "eslint": "^8.56.0" } }
  • 35. Common npm Commands: npm init : Initializes a new package.json file. npm install : Installs all dependencies listed in package.json . npm install <package-name> : Installs a specific package as a production dependency. npm install <package-name> --save-dev or npm install <package- name> -D : Installs a specific package as a development dependency. npm uninstall <package-name> : Uninstalls a package. npm update : Updates packages to their latest compatible versions. npm run <script-name> : Executes a script defined in the scripts section of package.json . Transpilers (Babel) JavaScript is constantly evolving, with new features being added regularly. However, not all browsers or Node.js environments support the latest features immediately. A transpiler (like Babel) converts modern JavaScript code (e.g., ES6+) into an older, backward-compatible version of JavaScript (e.g., ES5) that can run in a wider range of environments. How Babel Works: Babel takes your source code, parses it into an Abstract Syntax Tree (AST), transforms the AST based on configured plugins and presets, and then generates new code from the transformed AST. Presets: Collections of plugins that support a particular set of JavaScript features (e.g., @babel/preset-env for all modern JavaScript features). ``javascript // ES6+ source code const greet = (name) => Hello, ${name}!`; // Transpiled ES5 code (by Babel) var greet = function greet(name) { return "Hello, " + name + "!"; }; ```
  • 36. Bundlers (Webpack, Parcel) As JavaScript applications grow, they often consist of many modules and assets (CSS, images, fonts). Bundlers are tools that combine these separate modules and assets into a single (or a few) optimized bundles for deployment. This reduces the number of HTTP requests a browser needs to make, improving load times. Webpack: A highly configurable and powerful module bundler. It can handle various asset types through loaders and plugins. Parcel: A zero-configuration bundler that aims for a faster and easier development experience. Key functions of bundlers: * Module Resolution: Understands import and require statements to build a dependency graph. * Transpilation: Integrates with transpilers like Babel to convert modern JavaScript. * Minification: Removes unnecessary characters (whitespace, comments) from code to reduce file size. * Code Splitting: Divides code into smaller chunks that can be loaded on demand, improving initial load performance. * Asset Management: Can process and optimize other assets like CSS, images, and fonts. Linting (ESLint) Linting is the process of analyzing source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. Linters help enforce coding standards and identify potential problems early in the development cycle. ESLint: The most popular JavaScript linter. It is highly configurable and allows developers to define their own rules or use popular style guides (e.g., Airbnb, Standard). Benefits of Linting: * Code Quality: Catches common errors and anti-patterns. * Consistency: Ensures a consistent coding style across a team or project. * Early Detection: Identifies issues before they become harder to debug runtime errors. * Improved Readability: Consistent formatting and adherence to best practices make code easier to read and understand. Example ESLint rule:
  • 37. // Bad (ESLint would flag this) var x = 10; // Good const x = 10; These tools collectively form the backbone of a modern JavaScript development workflow, enabling developers to build complex, high-quality, and performant applications efficiently. 10. Best Practices and Tips Writing good JavaScript code goes beyond just knowing the syntax and features. Adhering to best practices, optimizing for performance, and understanding debugging techniques are crucial for building maintainable, scalable, and robust applications. Clean Code Principles Clean code is code that is easy to read, understand, and modify. Following these principles improves collaboration and reduces technical debt. Meaningful Names: Use descriptive names for variables, functions, and classes that clearly indicate their purpose. Avoid single-letter names or abbreviations unless they are universally understood (e.g., i for loop counters). ```javascript // Bad let d = new Date(); let val = calculate(x, y); // Good let currentDate = new Date(); let totalAmount = calculateTotalPrice(itemPrice, quantity); ``` Small Functions: Functions should do one thing and do it well. Keep functions short and focused, ideally no more than 20-30 lines of code. Avoid Global Variables: Minimize the use of global variables to prevent naming collisions and make code more modular. Use modules, closures, or IIFEs to encapsulate variables. Comments: Write comments that explain why the code does something, not what it does (the code itself should be self-explanatory). Remove commented- out code.
  • 38. Consistency: Maintain a consistent coding style (indentation, naming conventions, semicolon usage) across your entire codebase. Linters like ESLint can help enforce this. DRY (Don't Repeat Yourself): Avoid duplicating code. If you find yourself writing the same logic multiple times, extract it into a reusable function or module. Performance Optimization Optimizing JavaScript code ensures that your applications run smoothly and efficiently, providing a better user experience. Minimize DOM Manipulation: DOM operations are expensive. Batch changes, use document fragments, or update innerHTML once instead of multiple times. Avoid Layout Thrashing: Repeatedly reading and writing to the DOM can cause the browser to recalculate layout multiple times. Read all necessary layout properties first, then perform all writes. Optimize Loops: For large arrays, prefer for loops over forEach or map if performance is critical, as native loops can be faster. Cache array.length in for loops. javascript // Good for (let i = 0, len = arr.length; i < len; i++) { // ... } Debouncing and Throttling: For events that fire frequently (e.g., resize , scroll , mousemove , input ), use debouncing or throttling to limit the rate at which event handlers are executed. Lazy Loading: Load resources (images, components, modules) only when they are needed, reducing initial load time. Use const and let : Prefer const and let over var to improve scope management and prevent accidental reassignments, which can sometimes lead to minor performance benefits due to better optimization by JavaScript engines.
  • 39. Debugging Techniques Debugging is an essential skill for every developer. Modern browsers provide powerful developer tools to help you find and fix issues. console.log() : The simplest and most common debugging tool. Use console.log() , console.warn() , console.error() , console.table() , console.dir() to inspect values and program flow. Browser Developer Tools: Elements Tab: Inspect and modify HTML and CSS. Console Tab: View logs, errors, and execute JavaScript code. Sources Tab: Set breakpoints, step through code, inspect variables, and modify code on the fly. Network Tab: Monitor network requests and responses. Performance Tab: Analyze runtime performance. Memory Tab: Profile memory usage. Breakpoints: Pause code execution at specific lines to inspect the state of variables and the call stack. debugger keyword: Insert debugger; into your code to programmatically set a breakpoint. When the developer tools are open, execution will pause at this point. Error Messages: Pay close attention to error messages in the console. They often provide valuable clues about the type and location of the problem. Common Pitfalls and How to Avoid Them Loose Equality ( == ) vs. Strict Equality ( === ): Always use === (strict equality) to compare values, as == performs type coercion, which can lead to unexpected results. javascript console.log(0 == false); // true console.log(0 === false); // false console.log("5" == 5); // true console.log("5" === 5); // false
  • 40. Floating Point Inaccuracy: JavaScript numbers are 64-bit floating-point. This can lead to precision issues with decimal numbers. Avoid direct comparison of floating-point numbers. javascript console.log(0.1 + 0.2 === 0.3); // false this Context Issues: As discussed, this can be tricky. Be mindful of how functions are called and use arrow functions or bind / call / apply to control this when necessary. Asynchronous Code Complexity: Callback hell, unhandled promises, and race conditions are common. Use Promises and async/await to manage asynchronous flow effectively. Modifying Arrays While Iterating: Avoid adding or removing elements from an array while iterating over it with for...of or forEach , as this can lead to skipped elements or infinite loops. Iterate over a copy or use methods like filter or map to create new arrays. Global Scope Pollution: Declare variables within the narrowest possible scope to avoid unintended side effects and conflicts. By understanding and applying these best practices, you can write more efficient, readable, and maintainable JavaScript code, leading to more robust and successful applications.