Basics & Variables
Variable Declaration
| Keyword | Scope | Hoisting | Reassign | Redeclare |
|---|---|---|---|---|
var | Function | Yes (undefined) | ✅ | ✅ |
let | Block | Yes (TDZ) | ✅ | ❌ |
const | Block | Yes (TDZ) | ❌ | ❌ |
JavaScript
// Variables
var oldWay = "function scoped";
let modern = "block scoped";
const constant = "cannot reassign";
// Data Types
let str = "Hello"; // String
let num = 42; // Number
let float = 3.14; // Number
let bool = true; // Boolean
let nothing = null; // Null
let notDefined; // Undefined
let symbol = Symbol("id"); // Symbol
let bigInt = 9007199254740991n; // BigInt
// Type checking
console.log(typeof str); // "string"
console.log(typeof null); // "object" (JS quirk)
// Type conversion
let strNum = "123";
console.log(Number(strNum)); // 123
console.log(parseInt("123px")); // 123
console.log(String(123)); // "123"
console.log(Boolean(1)); // true
// Truthy and Falsy
// Falsy: false, 0, "", null, undefined, NaN
// Truthy: everything else
Functions
JavaScript
// Function Declaration (hoisted)
function greet(name) {
return `Hello, ${name}!`;
}
// Function Expression (not hoisted)
const greet2 = function(name) {
return `Hello, ${name}!`;
};
// Arrow Function (ES6)
const greet3 = (name) => `Hello, ${name}!`;
const greet4 = name => `Hello, ${name}!`; // Single param
const add = (a, b) => a + b; // Implicit return
// Arrow with body
const greet5 = (name) => {
const greeting = `Hello, ${name}!`;
return greeting;
};
// Default Parameters
const greet6 = (name = "Guest") => `Hello, ${name}!`;
// Rest Parameters
const sum = (...numbers) => numbers.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3, 4)); // 10
// Spread Operator
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
// Higher Order Functions
const numbers = [1, 2, 3, 4, 5];
// map - transform each element
const doubled = numbers.map(n => n * 2);
// filter - keep elements that pass test
const evens = numbers.filter(n => n % 2 === 0);
// reduce - accumulate to single value
const total = numbers.reduce((acc, n) => acc + n, 0);
// forEach - iterate without return
numbers.forEach(n => console.log(n));
// find - first element that passes test
const found = numbers.find(n => n > 3);
// some - at least one passes
const hasEven = numbers.some(n => n % 2 === 0); // true
// every - all pass
const allPositive = numbers.every(n => n > 0); // true
Arrays & Methods
JavaScript
// Array Creation
const arr = [1, 2, 3];
const arr2 = new Array(5); // Array of 5 undefined
const arr3 = Array.from("hello"); // ['h','e','l','l','o']
const arr4 = Array.of(1, 2, 3); // [1, 2, 3]
// Accessing
arr[0]; // 1
arr.at(-1); // 3 (last element, ES2022)
// Modifying (mutating)
arr.push(4); // Add to end
arr.pop(); // Remove from end
arr.unshift(0); // Add to beginning
arr.shift(); // Remove from beginning
arr.splice(1, 2); // Remove 2 items starting at index 1
arr.splice(1, 0, 'a', 'b'); // Insert at index 1
// Non-mutating
const sliced = arr.slice(1, 3); // Elements from index 1 to 2
const joined = arr.join(", "); // "1, 2, 3"
const concated = arr.concat([4, 5]);
// Searching
arr.indexOf(2); // 1 (-1 if not found)
arr.includes(2); // true
arr.findIndex(x => x > 1); // Index of first match
// Sorting
const nums = [3, 1, 4, 1, 5];
nums.sort((a, b) => a - b); // Ascending
nums.sort((a, b) => b - a); // Descending
nums.reverse();
// Destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first = 1, second = 2, rest = [3, 4, 5]
// Flat and FlatMap
const nested = [1, [2, [3, [4]]]];
nested.flat(); // [1, 2, [3, [4]]]
nested.flat(2); // [1, 2, 3, [4]]
nested.flat(Infinity); // [1, 2, 3, 4]
const arr5 = [1, 2, 3];
arr5.flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]
Objects
JavaScript
// Object Creation
const person = {
name: "Alice",
age: 25,
greet() {
return `Hello, I'm ${this.name}`;
}
};
// Shorthand properties (ES6)
const name = "Bob";
const age = 30;
const bob = { name, age }; // { name: "Bob", age: 30 }
// Computed properties
const key = "dynamic";
const obj = {
[key]: "value",
[`${key}_2`]: "value2"
};
// Access and modify
person.name; // "Alice"
person["name"]; // "Alice"
person.job = "Developer"; // Add property
delete person.age; // Delete property
// Object methods
Object.keys(person); // ["name", "age", "greet"]
Object.values(person); // ["Alice", 25, function]
Object.entries(person); // [["name", "Alice"], ...]
// Destructuring
const { name: userName, age: userAge } = person;
// Spread operator
const newPerson = { ...person, city: "NYC" };
// Object.assign
const merged = Object.assign({}, obj1, obj2);
// Optional chaining
const user = { profile: { name: "John" } };
console.log(user?.profile?.name); // "John"
console.log(user?.address?.city); // undefined (no error)
// Nullish coalescing
const value = null ?? "default"; // "default"
const value2 = 0 ?? "default"; // 0
// Object freeze/seal
Object.freeze(obj); // No changes allowed
Object.seal(obj); // No add/delete, but can modify
ES6+ Features
JavaScript
// Template Literals
const name = "Alice";
const greeting = `Hello, ${name}!`;
const multiline = `
This is
multiline
`;
// Classes
class Person {
#privateField = "secret"; // Private field (ES2022)
static count = 0; // Static property
constructor(name, age) {
this.name = name;
this.age = age;
Person.count++;
}
greet() {
return `Hello, I'm ${this.name}`;
}
get info() {
return `${this.name}, ${this.age}`;
}
set info(value) {
[this.name, this.age] = value.split(", ");
}
static createAnonymous() {
return new Person("Anonymous", 0);
}
}
class Employee extends Person {
constructor(name, age, salary) {
super(name, age);
this.salary = salary;
}
greet() {
return `${super.greet()}, I work here`;
}
}
// Map - key-value with any key type
const map = new Map();
map.set("key", "value");
map.set(123, "number key");
map.set({}, "object key");
map.get("key"); // "value"
map.has("key"); // true
map.delete("key");
map.size; // number of entries
// Set - unique values
const set = new Set([1, 2, 2, 3]);
set.add(4);
set.has(2); // true
set.delete(1);
set.size; // 3
// Symbol
const sym = Symbol("description");
const obj = {
[sym]: "symbol value"
};
// for...of (iterables)
for (const item of [1, 2, 3]) {
console.log(item);
}
for (const [key, value] of map) {
console.log(key, value);
}
Async JavaScript
JavaScript
// Callbacks
function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 1000);
}
// Promises
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
// reject(new Error("Failed"));
}, 1000);
});
promise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log("Done"));
// Promise methods
Promise.all([p1, p2, p3]) // All must resolve
.then(results => {});
Promise.allSettled([p1, p2]) // Wait for all to settle
.then(results => {});
Promise.race([p1, p2]) // First to settle
.then(result => {});
Promise.any([p1, p2]) // First to fulfill
.then(result => {});
// Async/Await
async function fetchUser() {
try {
const response = await fetch('/api/user');
const user = await response.json();
return user;
} catch (error) {
console.error("Error:", error);
}
}
// Parallel async operations
async function fetchAll() {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);
return { users, posts };
}
// Top-level await (ES2022, modules only)
const data = await fetch('/api/data').then(r => r.json());
// Fetch API
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' })
})
.then(response => response.json())
.then(data => console.log(data));
DOM Manipulation
JavaScript
// Selecting Elements
const el = document.getElementById('myId');
const el2 = document.querySelector('.myClass');
const els = document.querySelectorAll('div.item');
const els2 = document.getElementsByClassName('myClass');
// Creating Elements
const div = document.createElement('div');
div.textContent = 'Hello';
div.innerHTML = '<span>HTML content</span>';
div.id = 'newDiv';
div.className = 'container';
div.classList.add('active');
div.classList.remove('inactive');
div.classList.toggle('visible');
div.setAttribute('data-id', '123');
// Adding to DOM
document.body.appendChild(div);
parent.insertBefore(newEl, referenceEl);
parent.replaceChild(newEl, oldEl);
el.remove();
// Styles
el.style.color = 'red';
el.style.backgroundColor = 'blue';
const styles = getComputedStyle(el);
// Events
el.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log(e.target);
});
// Event Delegation
document.getElementById('list').addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log(e.target.textContent);
}
});
// Common Events
// click, dblclick, mouseenter, mouseleave
// keydown, keyup, keypress
// submit, change, input, focus, blur
// load, DOMContentLoaded, scroll, resize
// Form handling
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData);
});
// Local Storage
localStorage.setItem('key', JSON.stringify({ name: 'John' }));
const data = JSON.parse(localStorage.getItem('key'));
localStorage.removeItem('key');
localStorage.clear();
Closures & Scope
JavaScript
// Closure - function remembers its lexical scope
function createCounter() {
let count = 0; // Private variable
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.getCount(); // 2
// Practical use: Module pattern
const calculator = (function() {
let result = 0;
return {
add: (x) => result += x,
subtract: (x) => result -= x,
getResult: () => result
};
})();
// Closure in loops (common interview question)
// Problem
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// Logs: 3, 3, 3 (all same)
// Solution 1: let
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// Logs: 0, 1, 2
// Solution 2: IIFE
for (var i = 0; i < 3; i++) {
((j) => {
setTimeout(() => console.log(j), 1000);
})(i);
}
// Scope chain
const global = "global";
function outer() {
const outer = "outer";
function inner() {
const inner = "inner";
console.log(global, outer, inner); // All accessible
}
inner();
}
// Hoisting
console.log(x); // undefined (var hoisted)
var x = 5;
console.log(y); // ReferenceError (TDZ)
let y = 5;
this Keyword
JavaScript
// this in different contexts
// 1. Global context
console.log(this); // window (browser) / global (Node)
// 2. Object method
const obj = {
name: "Alice",
greet() {
console.log(this.name); // "Alice"
}
};
// 3. Regular function
function regular() {
console.log(this); // window/global (non-strict)
// undefined (strict mode)
}
// 4. Arrow function (lexical this)
const arrow = () => {
console.log(this); // Inherits from enclosing scope
};
const obj2 = {
name: "Bob",
greet: () => {
console.log(this.name); // undefined! (lexical this)
},
greetCorrect() {
const inner = () => {
console.log(this.name); // "Bob" (inherits from greetCorrect)
};
inner();
}
};
// 5. Event handlers
button.addEventListener('click', function() {
console.log(this); // The button element
});
button.addEventListener('click', () => {
console.log(this); // Lexical this (not the button!)
});
// Explicit binding
function greet() {
console.log(`Hello, ${this.name}`);
}
const person = { name: "Alice" };
// call - invoke immediately with args
greet.call(person); // "Hello, Alice"
greet.call(person, arg1, arg2);
// apply - same as call, but args as array
greet.apply(person, [arg1, arg2]);
// bind - returns new function with bound this
const boundGreet = greet.bind(person);
boundGreet(); // "Hello, Alice"
// 6. Constructor
function Person(name) {
this.name = name; // this = new object
}
const p = new Person("Alice");
Interview Key Points:
• Arrow functions don't have their own
•
•
• In callbacks,
• Arrow functions don't have their own
this•
bind returns a new function•
call and apply invoke immediately• In callbacks,
this can be unpredictable - use arrow functions or bind