Introduction to JavaScript
JavaScript was created by Brendan Eich in 1995 while he was working at Netscape. It was initially called Mocha, then renamed to LiveScript, and finally settled on the name JavaScript. The language was standardized as ECMAScript (ES) by ECMA International.
Why Learn JavaScript?
- It's used everywhere - frontend, backend (Node.js), mobile apps, desktop apps, and even AI tools.
- Works in all modern web browsers.
- Huge global community and high job demand.
- Foundation of popular frameworks like React, Angular, and Vue.
Writing JavaScript
You can embed JavaScript into an HTML page in three ways:
-
Inline Script:
<button onclick="alert('Hello!')">Click</button> -
Internal Script:
<script> alert("Welcome to JavaScript!"); </script> -
External Script:
<script src="script.js"></script>
JavaScript can be written in three main ways depending on how and where you want to include it in your HTML. Inline scripts are added directly to an HTML element's attribute like onclick. Internal scripts are placed inside a <script> tag within the HTML document, typically in the <head> or at the end of the <body>. External scripts are written in separate .js files and linked using the <script src="..."> tag. Using external files is best for keeping code organized and reusable.
Variables and Data Types
Declaring Variables
- var: function-scoped (older way)
- let: block-scoped (modern way)
- const: block-scoped, used for constants
In JavaScript, variables are used to store and manage data in a program...
Example:
var x = 10;
let y = 20;
const z = 30;
JavaScript variables store data values and are declared using var, let, or const. The var keyword is function-scoped and was commonly used in older code. let is block-scoped and allows reassignment, making it suitable for most cases in modern JavaScript. const is also block-scoped but cannot be reassigned, which makes it ideal for constants or values that should not change. Choosing the right keyword helps in writing clean and predictable code.
Data Types
| Type | Example |
|---|---|
| string | "Hello" |
| Number | 42 |
| Boolean | True, false |
| null | null |
| undefined | undefined |
| object | {name:"ali"} |
| symbol | symbol("id") |
| bigint | 123n |
JavaScript supports various data types to represent different kinds of values. These include primitive types such as string, number, boolean, null, undefined, symbol, and bigint. It also includes complex types like object. Understanding these data types is essential because they define how data is stored and manipulated in a program. For example, strings store text, numbers store numeric values, and objects can hold multiple values as key-value pairs.
Operators in JavaScript
- Arithmetic: +, -, *, /, %, ++, --
- Assignment: =, +=, -=, etc.
- Comparison: ==, ===, !=, !==, >, <, etc.
- Logical: &&, ||, !
- Bitwise: &, |, ^, ~, <<, >>
- Type Checking: typeof, instanceof
Operators in JavaScript are special symbols used to perform operations on values and variables. They help in tasks like arithmetic calculations, assigning values, comparing expressions, checking data types, and controlling logic flow. Arithmetic operators deal with basic math, assignment operators update variable values, and comparison operators are used in conditional statements. Logical operators are essential in making decisions based on multiple conditions, while bitwise operators perform low-level operations on binary representations. Understanding these operators is crucial for writing effective and logical JavaScript code.
Control Flow
if Statement
let score = 75;
if (score >= 50) {
console.log("You passed the test!");
}
The if statement in JavaScript is used to execute a block of code only if a specified condition is true. It helps control the flow of the program by making decisions based on given criteria. If the condition inside the parentheses evaluates to true, the code block inside the curly braces runs. If it's false, the block is skipped. This is commonly used in scenarios like checking user input, validating data, or determining outcomes based on values.
if-else Statement
let age = 17;
if (age >= 18)
{
console.log("You are eligible to vote.");
} else
{
console.log("You are not eligible to vote.");
}
The if-else statement allows you to execute one block of code if a condition is true, and another block if it is false. It provides an alternative path when the initial condition isn't met. This is useful for handling binary decisions, such as validating eligibility, toggling features, or responding to different user actions.
If-else if Statement
if (a > b)
{
console.log("A is greater");
} else if (a === b)
{
console.log("Equal");
} else
{
console.log("B is greater");
}
The if-else if statement is used to test multiple conditions in sequence. If the first condition is false, the program checks the next else if condition, and so on. This allows for more complex decision-making compared to a simple if-else structure.
Switch Statement
switch(day) {
case "Mon":
console.log("Monday");
break;
default:
console.log("Other day");
}
The switch statement is used to perform different actions based on different conditions. It evaluates an expression and executes the matching case block. The break statement prevents fall-through to the next case, and default runs if no cases match.
For Loop
for (let i = 0; i < 5; i++)
{
console.log(i);
}
The for loop is used to repeat a block of code a specific number of times. It includes three parts: initialization, condition, and increment/decrement. The loop continues running as long as the condition is true.
While Loop
let i = 0;
while (i < 5) {
console.log("Count:", i);
i++;
}
The while loop executes a block of code as long as the specified condition is true. It checks the condition before each iteration, making it ideal when the number of repetitions is not known in advance.
Do-While Loop
let i = 0;
do {
console.log("Value:", i);
i++;
} while (i < 5);
The do-while loop executes the block of code once before checking the condition. It guarantees that the code inside the loop runs at least once, making it useful when the loop must execute regardless of the initial condition.
For-in Loop
let person = { name: "Waleed", age: 25 };
for (let key in person) {
console.log(key + ": " + person[key]);
}
The for-in loop is used to iterate over the enumerable properties (keys) of an object. It allows you to access both the property names and their corresponding values, making it ideal for working with objects in JavaScript.
For-of Loop
let fruits = ["Apple", "Banana", "Mango"];
for (let fruit of fruits) {
console.log(fruit);
}
The for-of loop is used to iterate over iterable objects like arrays, strings, maps, etc. It retrieves the values directly rather than the keys or indices, making it ideal for array traversal.
Functions
function greet(name) {
return "Hello " + name;
}
const greetArrow = (name) => "Hello " + name;
Function Features
- Default Parameters
- Rest Parameters
- Spread Operator
- Callback Functions
- Anonymous Functions
- IIFE (Immediately Invoked Function Expressions)
- Closures
- Recursion
JavaScript functions come with advanced features that enhance flexibility and power. You can use default parameters to provide fallback values, rest parameters to handle multiple arguments, and the spread operator to expand arrays. Functions can also be anonymous or used as callbacks for asynchronous tasks. IIFEs run immediately after definition, closures allow inner functions to access outer variables, and recursion enables functions to call themselves for repeated operations.
Arrays
let numbers = [1, 2, 3];
numbers.push(4); // [1,2,3,4]
Useful Array Methods
- .push(), .pop(), .shift(), .unshift()
- .map(), .filter(), .reduce()
- .sort(), .reverse()
- .includes(), .indexOf()
Arrays in JavaScript are used to store multiple values in a single variable. They are zero-indexed and come with many built-in methods for manipulation. Methods like .push() and .pop() add or remove items at the end, while .shift() and .unshift() work at the beginning. You can transform arrays using .map(), filter them with .filter(), or reduce them to a single value using .reduce(). Searching and ordering are done with methods like .includes(), .indexOf(), .sort(), and .reverse().
Objects
let user = {
name: "Waleed",
age: 25,
greet() {
console.log("Hi!");
}
};
Object Methods
- Object.keys()
- Object.values()
- Object.entries()
- Object destructuring: const { name, age } = user;
Objects in JavaScript are collections of key-value pairs used to store and organize data. Each property has a name (key) and a value. Functions can also be included as methods. Common methods like Object.keys(), Object.values(), and Object.entries() are useful for accessing object data. JavaScript also supports object destructuring, which allows you to extract properties into variables directly using syntax like const { name, age } = user;.
DOM Manipulation
Selectors
document.getElementById("id");
document.querySelector(".class");
Modify Elements
element.innerHTML = "New content";
element.style.color = "red";
Events
btn.addEventListener("click", function() {
alert("Clicked!");
});
The DOM (Document Object Model) allows JavaScript to interact with and manipulate HTML content dynamically. Using selectors like getElementById() and querySelector(), you can access elements. You can then modify their content or styles using properties like innerHTML and style. JavaScript also enables event handling, allowing you to respond to user actions (e.g., clicks) using addEventListener().
Advanced Concepts
Closures
function outer() {
let x = 0;
return function() {
x++;
return x;
};
}
Callbacks
function load(callback) {
callback("Data loaded!");
}
Promises
let promise = new Promise((resolve, reject) => {
resolve("Success");
});
Async/Await
async function getData() {
let data = await fetch("url");
}
Advanced JavaScript concepts allow developers to handle asynchronous operations and create more complex behavior. Closures enable inner functions to access variables from outer functions even after the outer function has finished executing. Callbacks are functions passed as arguments and executed later, often used in asynchronous tasks. Promises provide a cleaner way to work with asynchronous code, representing future values. Async/Await simplifies promise handling, making asynchronous code look and behave like synchronous code for better readability.
Error Handling
try {
// code
} catch (error) {
console.log(error.message);
}
Error handling in JavaScript is done using try-catch blocks. The try block contains code that may throw an error, while the catch block handles any errors that occur. This helps prevent the program from crashing and allows developers to respond gracefully to unexpected issues.
Object-Oriented JavaScript
Object-Oriented JavaScript is a programming style that centers around the concept of objects...
Classes and Inheritance
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + " makes sound");
}
}
Object-Oriented JavaScript (OOJS) is a programming paradigm based on the concept of objects, which can contain data (properties) and code (methods). JavaScript supports object-oriented features like encapsulation, inheritance, and polymorphism. Using class syntax introduced in ES6, you can create reusable blueprints for objects and build complex applications more effectively.
JavaScript Modules
// file.js
export const sum = (a, b) => a + b;
// main.js
import { sum } from "./file.js";
JavaScript modules allow you to split code into separate files, making it more organized and maintainable. Using export and import keywords, you can share variables, functions, or classes between files. This helps keep code modular and reusable, especially in large applications.
Browser APIs
- Local Storage
localStorage.setItem("user", "Ali");
- Geolocation API
- Fetch API
- Canvas API
- Web Storage API
- Drag and Drop API
Browser APIs are built-in interfaces provided by web browsers that allow developers to interact with and control the browser's functionality and the environment. These APIs let you do things like store data locally, get the user's location, fetch data from servers, draw graphics, and implement drag-and-drop functionality. They're essential for creating dynamic and interactive web applications.
ES6+ Features
- Arrow Functions
- let/const
- Template Literals
- Destructuring
- Modules
- Promises
- Optional Chaining (obj?.name)
- Nullish Coalescing (??)
- Spread and Rest (...)
ES6 and newer versions of JavaScript introduced many powerful features that simplify coding and improve performance. These include arrow functions for shorter syntax, let and const for better variable control, template literals for easier string handling, destructuring for unpacking data, and modules for organizing code. It also brought modern tools like promises, optional chaining, nullish coalescing, and the spread/rest operators that make JavaScript more readable and maintainable.
Tools and Ecosystem
- Node.js
- NPM/Yarn
- Babel (Transpiler)
- Webpack, Parcel
- ESLint, Prettier
- TypeScript (JS with types)
JavaScript development is supported by a rich ecosystem of tools. Node.js allows you to run JavaScript outside the browser, while NPM and Yarn are package managers for installing libraries. Babel is used to convert modern JavaScript into backward-compatible versions. Bundlers like Webpack and Parcel optimize and combine code. Tools such as ESLint and Prettier help maintain code quality, and TypeScript brings static typing to JavaScript for more robust development.
JavaScript Frameworks
- React - Component-based UI library
- Vue - Progressive framework
- Angular - Full-featured framework
- Svelte - Compiled framework
- Next.js / Nuxt.js - Meta-frameworks
JavaScript frameworks simplify the process of building dynamic web applications. React is a popular library for building user interfaces with reusable components. Vue offers a flexible and beginner-friendly approach. Angular is a comprehensive framework with built-in tools and powerful features. Svelte compiles components into efficient JavaScript code. Frameworks like Next.js (for React) and Nuxt.js (for Vue) provide advanced features like server-side rendering and static site generation.
JavaScript Best Practices
- Use === instead of ==
- Avoid global variables
- Use let and const, not var
- Use arrow functions for callbacks
- Always handle errors in async code
- Modularize your code
Following best practices in JavaScript ensures code is clean, efficient, and maintainable. Always prefer === for strict comparisons to avoid unexpected type coercion. Limit the use of global variables to prevent conflicts. Use let and const for proper variable scoping. Arrow functions are ideal for concise callbacks. Handle errors in asynchronous code using try...catch or .catch() with promises. Organizing your code into modules improves readability and reusability.
Sample Projects (With Ideas)
- Todo App with Local Storage
- Calculator with Keyboard Support
- Weather App using API
- Quiz Game
- Digital Clock
- Typing Speed Test
- Form Validator
- Memory Card Game
- Expense Tracker
- Portfolio Website
Practice Questions
- What is hoisting in JavaScript?
- Difference between let, var, and const?
- How does closure work?
- What is event delegation?
- What is the call stack?
Interview Prep & Advanced Patterns
- Prototype chain
- Debouncing and Throttling
- Currying
- Memoization
- Module pattern
- Singleton pattern
- Factory vs Constructor
- Call, Bind, Apply
Click here for online CSS Code reader.
Click here to download VS CODE.
Click to go back Home.