JavaScript Basics to Intermediate: Everything You Need in One Place
JavaScript can feel huge. This guide brings the most important topics together: variables, data types, functions, objects, arrays, promises, async/await, DOM events, and more. Each section has short explanations and smal
JavaScript can feel huge. This guide brings the most important topics together: variables, data types, functions, objects, arrays, promises, async/await, DOM events, and more. Each section has short explanations and small examples so you can learn fast and use them in real projects.
1. Variables: var, let, const
Variables store data.
var name = "Arun"; // old way, function-scoped
let age = 20; // block-scoped, can change
const city = "Chennai"; // block-scoped, cannot reassign
- Use let when the value changes.
- Use const by default (safer).
- Avoid var in new code.
2. Data Types: Primitive vs Non-Primitive
Primitive types (stored by value)
- string: "hello"
- number: 10, 3.14
- boolean: true, false
- null: intentional empty value
- undefined: variable declared but not assigned
- symbol, bigint (advanced)
let a = 10;
let b = a; // b gets a copy of 10
b = 20;
console.log(a); // 10
Non-primitive (reference) types
- object: { name: "Arun" }
- array: [1, 2, 3]
- function: function sayHi() {}
let obj1 = { name: "Arun" };
let obj2 = obj1; // same reference
obj2.name = "Kumar";
console.log(obj1.name); // "Kumar"
3. Memory Management & Garbage Collection
JavaScript automatically allocates memory for variables and objects and frees it when no longer needed. This is called garbage collection.
- Primitives are usually stored on the stack.
- Objects/arrays/functions are stored on the heap, variables hold references.
- If you keep references (e.g., in global variables, closures, or event listeners), memory cannot be freed β memory leak. Good practice: remove unused event listeners, avoid big objects in long-lived closures.
*4. Functions, Constructors, and this
*
Normal function
function add(a, b) {
return a + b;
}
Arrow function (ES6)
const add = (a, b) => a + b;
Constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
const p = new Person("Arun", 20);
new creates a new object and sets this to that object.
5. Arrays: Important Methods
const nums = [1, 2, 3, 4, 5];
forEach
nums.forEach(n => console.log(n));
map (transform)
const doubled = nums.map(n => n * 2); // [2,4,6,8,10]
filter (select)
const evens = nums.filter(n => n % 2 === 0); // [2,4]
find vs filter
- find: returns first matching element.
- filter: returns array of all matching elements.
const firstEven = nums.find(n => n % 2 === 0); // 2
const allEvens = nums.filter(n => n % 2 === 0); // [2,4]
slice
const part = nums.slice(1, 3); // [2,3] (end not included)
reduce
const sum = nums.reduce((acc, n) => acc + n, 0); // 15
_includes vs indexOf
_
nums.includes(3); // true
nums.indexOf(3); // 2 (index) or -1 if not found
Use includes to check existence, indexOf if you need position.
6. Strings: Common Methods
const text = " Hello World ";
text.trim(); // "Hello World"
text.toLowerCase(); // " hello world "
text.toUpperCase(); // " HELLO WORLD "
text.includes("World"); // true
text.slice(0, 5); // " Hel"
text.split(" "); // ["", "", "Hello", "World", "", ""]
7. Objects
const user = {
name: "Arun",
age: 20,
greet() {
console.log(`Hi, I am ${this.name}`);
}
};
user.greet(); // Hi, I am Arun
Access:
user.name; // dot
user["age"]; // bracket
8. Spread vs Rest Operator (...)
Same symbol, different use.
Spread (expand)
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1,2,3,4]
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a:1, b:2 }
Rest (collect)
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
In function parameters or destructuring, ... is rest. In arrays/objects literals or function calls, itβs spread.
## 9. Conditional Operator & switch
Ternary (conditional) operator
const age = 18;
const status = age >= 18 ? "adult" : "minor";
switch
const day = "Mon";
switch (day) {
case "Mon":
console.log("Monday");
break;
case "Tue":
console.log("Tuesday");
break;
default:
console.log("Other day");
}
10. Loops: for, break, continue
for (let i = 0; i < 5; i++) {
if (i === 2) continue; // skip 2
if (i === 4) break; // stop at 4
console.log(i); // 0,1,3
}
- break: exit loop.
- continue: skip current iteration. Also: for...in (object keys), for...of (iterables).
const obj = { a: 1, b: 2 };
for (const key in obj) {
console.log(key, obj[key]);
}
11. == vs ===
0 == "0"; // true (type conversion)
0 === "0"; // false (different types)
Always prefer === and !== to avoid bugs
12. null vs undefined
- undefined: variable declared but no value assigned.
- null: intentional empty value.
let x;
console.log(x); // undefined
let y = null;
console.log(y); // null
13. Hoisting, Scope, and Closures
Hoisting
Variable declarations (var) and function declarations are moved to the top of their scope before execution.
console.log(a); // undefined (hoisted)
var a = 5;
// But with let/const:
console.log(b); // ReferenceError
let b = 10;
Functions are fully hoisted:
sayHi(); // works
function sayHi() {
console.log("Hi");
}
Scope
- var: function scope.
- let, const: block scope ({}).
{
let x = 1;
}
// x is not accessible here
Closure
A function that remembers variables from its outer scope.
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
count is βclosed overβ by the inner function.
14. Promises: then, catch, resolve, reject
Promise = value that may come later (e.g., API response).
const p = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Done");
} else {
reject("Error");
}
});
p
.then(res => console.log(res))
.catch(err => console.error(err));
- resolve(value): success.
- reject(error): failure.
- then: handle success.
- catch: handle error
- async / await and try / catch async/await makes promises look like normal code.
async function fetchData() {
try {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
console.log(data);
} catch (err) {
console.error("Fetch failed", err);
}
}
- async function always returns a promise.
- await waits for a promise inside async.
- Use try/catch for errors.
16. Axios (API calls)
Axios is a popular HTTP client.
npm install axios
import axios from "axios";
async function getUsers() {
try {
const res = await axios.get("https://api.example.com/users");
console.log(res.data);
} catch (err) {
console.error(err);
}
}
Sync vs async:
- Normal function calls are sync (run line by line).
- API calls with fetch/axios are async (donβt block UI).
17. setTimeout, setInterval, and Cleanup
// Run once after 1 second
const timerId = setTimeout(() => {
console.log("One time");
}, 1000);
// Run every 2 seconds
const intervalId = setInterval(() => {
console.log("Repeated");
}, 2000);
// Cleanup
clearTimeout(timerId);
clearInterval(intervalId);
Always clear intervals/timeouts in useEffect cleanup (React) or when component unmounts to avoid memory leaks
18. Event Loop (How JS Runs Async Code)
JavaScript is single-threaded but handles async tasks using:
Call stack: where functions run.
- Web APIs (browser): setTimeout, fetch, DOM events.
- Callback queue: ready callbacks.
- Event loop: moves callbacks from queue to stack when stack is empty.
- This is why setTimeout doesnβt block other code.
19. DOM Events: onclick, onchange, oninput, addEventListener
HTML:
<button id="btn">Click</button>
<input id="name" />
JS:
const btn = document.getElementById("btn");
const input = document.getElementById("name");
// Old style
btn.onclick = () => {
console.log("Clicked");
};
// Better: addEventListener
btn.addEventListener("click", () => {
console.log("Clicked with listener");
});
input.addEventListener("change", e => {
console.log("Changed", e.target.value);
});
input.addEventListener("input", e => {
console.log("Typing...", e.target.value);
});
Common events: click, change, input, submit, keydown, etc.
- Callbacks, forEach, for...in
Callback
Function passed into another function.
function doSomething(callback) {
callback();
}
doSomething(() => console.log("Done"));
forEach with callback
[1, 2, 3].forEach((n, index) => {
console.log(index, n);
});
for...in (object keys)
const user = { name: "Arun", age: 20 };
for (const key in user) {
console.log(key, user[key]);
}
21. Map vs forEach vs filter
- map: returns new array (transform).
- forEach: no return, just loop (side effects).
- filter: returns new array (subset).
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2); // [2,4,6]
const evens = nums.filter(n => n % 2 === 0); // [2]
nums.forEach(n => console.log(n)); // logs 1,2,3
Use map when you need a new array, forEach only for logging or side effects
22. flatMap
flatMap = map + flat (one level).
const arr = [[1], [2, 3], [4]];
const flat = arr.flatMap(x => x); // [1,2,3,4]
Useful when mapping to arrays and you want them flattened.
- JSON, Parameters vs Arguments
JSON
const obj = { name: "Arun", age: 20 };
const jsonStr = JSON.stringify(obj); // to string
const parsed = JSON.parse(jsonStr); // back to object
Parameters vs Arguments
function add(a, b) { // a, b are parameters
return a + b;
}
add(2, 3); // 2, 3 are arguments
- Real-Time Example: Putting It All Together
Imagine a simple βUser Searchβ feature:
- Input box for name.
- Button to search.
- Show list of users from an API.
<input id="search" placeholder="Search user" />
<button id="searchBtn">Search</button>
<ul id="list"></ul>
import axios from "axios";
const input = document.getElementById("search");
const btn = document.getElementById("searchBtn");
const list = document.getElementById("list");
let intervalId = null;
// Debounce with setInterval (simple example)
input.addEventListener("input", () => {
if (intervalId) clearInterval(intervalId);
intervalId = setInterval(async () => {
clearInterval(intervalId);
const query = input.value.trim();
if (!query) return;
try {
const res = await axios.get(
`https://api.example.com/users?q=${query}`
);
const users = res.data; // assume array
list.innerHTML = "";
users.forEach(user => {
const li = document.createElement("li");
li.textContent = user.name;
list.appendChild(li);
});
} catch (err) {
console.error(err);
}
}, 500);
});
btn.addEventListener("click", async () => {
const query = input.value.trim();
if (!query) return;
try {
const res = await axios.get(
`https://api.example.com/users?q=${query}`
);
const users = res.data;
list.innerHTML = "";
users
.filter(u => u.active)
.map(u => u.name)
.forEach(name => {
const li = document.createElement("li");
li.textContent = name;
list.appendChild(li);
});
} catch (err) {
console.error(err);
}
});
This example uses:
- Variables (let, const)
- Arrow functions
- DOM events (input, click)
- async/await, try/catch
- Axios
- map, filter, forEach
- setInterval + cleanup
- Quick Comparison Cheat Sheet
- var vs let vs const: scope & reassignment rules.
- == vs ===: type conversion vs strict.
- includes vs indexOf: boolean vs index.
- find vs filter: one item vs array.
- map vs forEach: returns array vs no return.
- map vs filter: transform vs select.
- Spread vs Rest: expand vs collect
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.