JavaScript, one concept at a time.
A complete practical guide with runnable examples for state, strings, logic, loops, functions, objects, DOM interactions, timers, async flows and APIs.
Variables
Store and manage data in your programs.
const by default, switch to let only when a value really changes, and avoid var because it behaves in older, more error-prone ways.
const userName = 'Adrian'; const planName = 'Pro'; let openProjects = 3; openProjects = openProjects + 1; console.log(`${userName} uses ${planName}`); console.log('Open projects:', openProjects); // → Adrian uses Pro // → Open projects: 4
const userEmail = 'john@example.com'; const totalPrice = 99.99; const isLoggedIn = true; const lastLoginDate = '2026-04-10'; console.log(userEmail); console.log(totalPrice); console.log(isLoggedIn); console.log(lastLoginDate); // Compare this with vague names like data, value, item, temp
let buttonLabel = 'Save draft'; console.log(buttonLabel); const hasChanges = true; if (hasChanges) { buttonLabel = 'Publish changes'; } console.log(buttonLabel); // → Publish changes
const project = { name: 'LiveJS', theme: 'Midnight', activeUsers: 1200 }; project.activeUsers = 1225; project.theme = 'Sunrise'; console.log(project); // const prevents reassignment of the variable itself, not changes inside the object
Scope
Where variables are accessible in your code.
const appName = 'LiveJS'; function renderHeader() { const pageTitle = 'Editor'; console.log(appName); // → LiveJS console.log(pageTitle); // → Editor } renderHeader(); console.log(appName); // → LiveJS // console.log(pageTitle); // Error: only exists inside renderHeader
const email = 'team@example.com'; if (email.includes('@')) { const message = 'Email format looks correct.'; console.log(message); } // console.log(message); // Error: message is scoped to the if block if (true) { var legacyNote = 'var escapes the block'; } console.log(legacyNote); // → var escapes the block
const brand = 'LiveJS'; function openWorkspace() { const section = 'Projects'; function openProject() { const projectName = 'Landing Revamp'; console.log(brand, section, projectName); // → LiveJS Projects Landing Revamp } openProject(); } openWorkspace();
function startPreview() { const previewTheme = 'midnight'; console.log('Preview theme:', previewTheme); } startPreview(); // Good: previewTheme stays local to the function // Bad: assigning without let/const would leak a global value
Data Types
The different kinds of values JavaScript works with.
null, and undefined, plus reference types like arrays and objects. Knowing the type of a value matters constantly: form input arrives as strings, API data may contain null, booleans drive UI state, and converting values safely avoids subtle bugs.
const pageTitle = 'Dashboard'; // string const openTabs = 3; // number const isPreviewOpen = true; // boolean let selectedTheme; // undefined const currentUser = null; // null console.log(pageTitle, openTabs, isPreviewOpen, selectedTheme, currentUser);
const response = { title: 'Launch checklist', views: 120, published: false, tags: ['release', 'ops'] }; console.log(typeof response.title); // → string console.log(typeof response.views); // → number console.log(typeof response.published); // → boolean console.log(Array.isArray(response.tags)); // → true
const quantityInput = '4'; const newsletterValue = 'true'; const quantity = Number(quantityInput); const wantsNewsletter = newsletterValue === 'true'; console.log(quantity + 1); // → 5 console.log(wantsNewsletter); // → true
let draftTitle; const selectedProject = null; console.log(draftTitle); // → undefined console.log(selectedProject); // → null // undefined = not assigned yet // null = intentionally empty
String Manipulation
Work with text: template literals, methods, and formatting.
const firstName = 'Mara'; const unreadCount = 4; const message = `Welcome back, ${firstName}. You have ${unreadCount} unread messages.`; console.log(message); // → Welcome back, Mara. You have 4 unread messages.
const rawEmail = ' TEAM@EXAMPLE.COM '; const cleanEmail = rawEmail.trim().toLowerCase(); console.log(cleanEmail); // → team@example.com console.log(cleanEmail.includes('@')); // → true console.log(cleanEmail.endsWith('.com')); // → true
const articleTitle = 'How to Build a Fast Landing Page'; const slug = articleTitle .toLowerCase() .replaceAll(' ', '-'); console.log(slug); // → how-to-build-a-fast-landing-page
const tags = 'html, css, javascript, performance'; const tagList = tags .split(',') .map(tag => tag.trim()) .join(' | '); console.log(tagList); // → html | css | javascript | performance
const fileName = 'hero-background.webp'; const extension = fileName.slice(fileName.lastIndexOf('.') + 1); console.log(extension); // → webp console.log(fileName.startsWith('hero')); // → true
Conditions
Make decisions based on values with if, else, and switch.
const projectsCount = 14; if (projectsCount >= 20) { console.log('Enterprise plan'); } else if (projectsCount >= 10) { console.log('Pro plan'); } else if (projectsCount >= 1) { console.log('Starter plan'); } else { console.log('No active plan yet'); }
const isLoggedIn = true; const hasVerifiedEmail = true; const isSuspended = false; if (isLoggedIn && hasVerifiedEmail && !isSuspended) { console.log('User can publish updates.'); } const canPreview = isLoggedIn && (hasVerifiedEmail || !isSuspended); console.log('Preview access:', canPreview); // → Preview access: true
const hasUnsavedChanges = false; const buttonText = hasUnsavedChanges ? 'Save changes' : 'Saved'; const badgeTone = hasUnsavedChanges ? 'warning' : 'success'; console.log(buttonText); console.log(badgeTone);
const route = '/settings'; switch (route) { case '/': console.log('Render home page'); break; case '/editor': console.log('Render editor page'); break; case '/settings': console.log('Render settings page'); break; default: console.log('Render 404 page'); }
Loops
Repeat code with for, while, and for...of.
let pagination = ''; for (let page = 1; page <= 5; page++) { pagination += `[${page}] `; } console.log(pagination.trim()); // → [1] [2] [3] [4] [5]
let attempt = 1; let connected = false; while (!connected && attempt <= 3) { console.log(`Trying connection #${attempt}`); connected = attempt === 3; attempt++; } console.log('Connected:', connected); // → Connected: true
const notifications = [ 'New comment', 'Build completed', 'Payment received' ]; for (const notification of notifications) { console.log(`Inbox item: ${notification}`); } notifications.forEach((notification, index) => { console.log(`${index + 1}. ${notification}`); }); // → 1. New comment // → 2. Build completed // → 3. Payment received
const fields = ['email', '', 'password', 'timezone']; for (const field of fields) { if (!field) { console.log('Skipping empty field'); continue; } if (field === 'password') { console.log('Sensitive field found, stop logging.'); break; } console.log('Checking:', field); } // → Checking: email // → Skipping empty field // → Sensitive field found, stop logging.
for (let row = 1; row <= 3; row++) { let line = ''; for (let col = 1; col <= 4; col++) { line += `[${row},${col}] `; } console.log(line.trim()); }
Functions
Reusable blocks of code. The building block of every JS program.
function formatUserLabel(name, role) { return `${name.trim()} · ${role.toUpperCase()}`; } const formatStatus = status => `Status: ${status.toLowerCase()}`; console.log(formatUserLabel(' Adrian ', 'mentor')); console.log(formatStatus('ACTIVE')); // → Adrian · MENTOR // → Status: active
function calculateInvoiceTotal(taxRate = 0.19, ...items) { const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0); return +(subtotal * (1 + taxRate)).toFixed(2); } const total = calculateInvoiceTotal( 0.19, { price: 120, qty: 1 }, { price: 35, qty: 2 } ); console.log('Invoice total:', total); // → 226.1
function validateField(label, value, rule) { if (!rule(value)) { return `${label} is invalid`; } return `${label} looks good`; } const emailRule = text => text.includes('@') && text.includes('.'); console.log(validateField('Email', 'team@example.com', emailRule)); console.log(validateField('Email', 'wrong-value', emailRule));
function buildOrderSummary(customer, items) { const total = items.reduce((sum, item) => sum + item.price, 0); return { customer, itemCount: items.length, total, message: `${customer} ordered ${items.length} items.` }; } const summary = buildOrderSummary('Mara', [ { name: 'Notebook', price: 24 }, { name: 'Pen set', price: 11 } ]); console.log(summary.message); console.log(summary.total); // → 35
const trim = value => value.trim(); const lowercase = value => value.toLowerCase(); const toSlug = value => value.replaceAll(' ', '-'); function pipe(value, ...steps) { return steps.reduce((current, step) => step(current), value); } const slug = pipe(' Summer Sale Banner ', trim, lowercase, toSlug); console.log(slug); // → summer-sale-banner
Closures
Functions that "remember" their surrounding scope.
function createDraftTracker() { let lastSavedAt = 'not saved yet'; return function markSaved(time) { lastSavedAt = time; console.log(`Draft saved at ${lastSavedAt}`); }; } const saveDraft = createDraftTracker(); saveDraft('10:45'); saveDraft('10:52');
function makeCounter() { let count = 0; return { increment: () => ++count, decrement: () => --count, get: () => count }; } const counter = makeCounter(); console.log(counter.increment()); // → 1 console.log(counter.increment()); // → 2 console.log(counter.decrement()); // → 1
function createRequestLabel(prefix) { return id => `${prefix}-${id}`; } const draftLabel = createRequestLabel('draft'); const publishLabel = createRequestLabel('publish'); console.log(draftLabel(101)); // → draft-101 console.log(publishLabel(101)); // → publish-101
function createPriceFormatter() { const cache = {}; return amount => { if (cache[amount]) return cache[amount]; cache[amount] = `$${amount.toFixed(2)}`; return cache[amount]; }; } const formatPrice = createPriceFormatter(); console.log(formatPrice(49)); console.log(formatPrice(49)); // same cached result
Arrays
Ordered lists of values. Master map, filter and reduce.
map), filter what you need (filter), combine values (reduce), search quickly (find, some, every), and organize items with helpers like sort, slice, includes, and at.
const nums = [1, 2, 3, 4, 5]; const doubled = nums.map(n => n * 2); console.log(doubled); // → [2,4,6,8,10] const evens = nums.filter(n => n % 2 === 0); console.log(evens); // → [2, 4]
const prices = [9.99, 4.50, 14.99, 2.00]; const total = prices.reduce( (sum, price) => sum + price, 0 ); console.log(total.toFixed(2)); // → 31.48
const users = [ { name: 'Ana', age: 22 }, { name: 'Mihai', age: 17 }, ]; const adult = users.find(u => u.age >= 18); console.log(adult.name); // → Ana const hasMinor = users.some(u => u.age < 18); console.log(hasMinor); // → true
const tasks = ['Write brief', 'Review copy']; tasks.push('Publish update'); console.log(tasks); // → 3 tasks const today = tasks.slice(0, 2); console.log(today); // → first 2 tasks const prices = [19, 5, 12]; const sorted = [...prices].sort((a, b) => a - b); console.log(sorted); // → [5, 12, 19]
const cart = [ { name: 'Keyboard', price: 99, qty: 1 }, { name: 'Mouse', price: 49, qty: 2 }, { name: 'Cable', price: 12, qty: 3 }, ]; const labels = cart.map(item => `${item.name} x${item.qty}`); const total = cart.reduce((sum, item) => sum + item.price * item.qty, 0); console.log(labels); console.log(`Total: $${total}`);
const statuses = ['draft', 'review', 'published']; console.log(statuses.includes('review')); // → true console.log(statuses.at(-1)); // → published const [first, second] = statuses; console.log(first, second); // → draft review const [, , last] = statuses; console.log(last); // → published
const posts = [ { title: 'Design system', tags: ['css', 'ui'] }, { title: 'Launch checklist', tags: ['ops', 'ui'] }, ]; const allTags = posts.flatMap(post => post.tags); const uniqueTags = [...new Set(allTags)].sort(); console.log(allTags); // → ['css', 'ui', 'ops', 'ui'] console.log(uniqueTags); // → ['css', 'ops', 'ui']
Objects
Key-value pairs for structured data. The foundation of JS.
const user = { name: 'Ana', age: 25, city: 'Cluj' }; const { name, age } = user; console.log(name, age); // → Ana 25 const updated = { ...user, age: 26 }; console.log(updated.age); // → 26
const scores = { Ana: 90, Mihai: 75, Ion: 88 }; console.log(Object.keys(scores)); // → ['Ana', 'Mihai', 'Ion'] console.log(Object.values(scores)); // → [90, 75, 88]
const config = { db: { host: 'localhost', port: 5432 } }; console.log(config?.db?.host); // → localhost console.log(config?.cache?.host); // → undefined const port = config?.cache?.port ?? 6379; console.log(port); // → 6379
const profile = { name: 'Elena', contact: { email: 'elena@studio.dev', city: 'Bucharest' }, plan: 'starter', }; const upgraded = { ...profile, plan: 'pro', contact: { ...profile.contact, city: 'Cluj-Napoca' }, }; console.log(upgraded.plan); // → pro console.log(upgraded.contact.city); // → Cluj-Napoca
const settings = { theme: 'dark', notifications: true, language: 'en', }; const labels = Object.entries(settings).map( ([key, value]) => `${key}: ${value}` ); const upperKeys = Object.fromEntries( Object.entries(settings).map(([key, value]) => [key.toUpperCase(), value]) ); console.log(labels); console.log(upperKeys);
const account = { owner: 'Mara', balance: 1200, deposit(amount) { this.balance += amount; return this.balance; }, summary() { return `${this.owner}: $${this.balance}`; } }; account.deposit(300); console.log(account.summary()); // → Mara: $1500
const defaultOptions = { pageSize: 20, sortBy: 'createdAt', showArchived: false, }; const userOptions = { pageSize: 50, showArchived: true, }; const finalOptions = Object.assign({}, defaultOptions, userOptions); console.log(finalOptions.pageSize); // → 50 console.log(finalOptions.sortBy); // → createdAt
Classes
Object-oriented programming with constructors and methods.
class Workspace { constructor(name, owner) { this.name = name; this.owner = owner; this.members = 1; } addMember() { this.members += 1; } summary() { return `${this.name} by ${this.owner} · ${this.members} members`; } } const workspace = new Workspace('Launch Board', 'Adrian'); workspace.addMember(); console.log(workspace.summary());
class Notification { constructor(message) { this.message = message; } show() { console.log(`Notice: ${this.message}`); } } class SuccessNotification extends Notification { show() { console.log(`Success: ${this.message}`); } } const notice = new SuccessNotification('Project published'); notice.show(); // → Success: Project published
class ProjectProgress { constructor() { this._value = 0; } get label() { return `${this._value}% complete`; } set value(nextValue) { this._value = Math.max(0, Math.min(100, nextValue)); } } const progress = new ProjectProgress(); progress.value = 72; console.log(progress.label); // → 72% complete progress.value = 140; console.log(progress.label); // → 100% complete
class ColorTheme { static fromMode(mode) { return mode === 'dark' ? '#020617' : '#f8fafc'; } } console.log(ColorTheme.fromMode('dark')); console.log(ColorTheme.fromMode('light'));
DOM
Select, modify and react to elements on the page.
const title = document.querySelector('[data-product-title]'); const price = document.querySelector('[data-product-price]'); const badge = document.querySelector('[data-product-badge]'); title.textContent = 'Wireless Keyboard'; price.textContent = '$89'; badge.textContent = 'In stock'; badge.classList.add('is-live');
const form = document.querySelector('form'); const message = document.querySelector('[data-message]'); form.addEventListener('submit', event => { event.preventDefault(); const email = form.email.value.trim(); message.textContent = email.includes('@') ? `Invite sent to ${email}` : 'Please enter a valid email address.'; });
const tasks = [ { title: 'Write landing copy', done: true }, { title: 'Review CTA button', done: false }, { title: 'Publish update', done: false } ]; const list = document.querySelector('[data-task-list]'); list.innerHTML = tasks.map(task => `${task.title} `).join('');
const menu = document.querySelector('[data-menu]'); const status = document.querySelector('[data-status]'); menu.addEventListener('click', event => { const button = event.target.closest('button[data-view]'); if (!button) return; status.textContent = `Active view: ${button.dataset.view}`; });
const toggle = document.querySelector('[data-toggle-theme]'); const panel = document.querySelector('[data-panel]'); toggle.addEventListener('click', () => { panel.classList.toggle('dark'); toggle.textContent = panel.classList.contains('dark') ? 'Switch to light' : 'Switch to dark'; });
const openButton = document.querySelector('[data-open-modal]'); const closeButton = document.querySelector('[data-close-modal]'); const modal = document.querySelector('[data-modal]'); openButton.addEventListener('click', () => { modal.hidden = false; }); closeButton.addEventListener('click', () => { modal.hidden = true; });
const tabs = document.querySelectorAll('[data-tab]'); const panels = document.querySelectorAll('[data-panel-name]'); tabs.forEach(tab => { tab.addEventListener('click', () => { panels.forEach(panel => { panel.hidden = panel.dataset.panelName !== tab.dataset.tab; }); }); });
const search = document.querySelector('[data-search]'); const items = document.querySelectorAll('[data-item]'); search.addEventListener('input', () => { const term = search.value.trim().toLowerCase(); items.forEach(item => { item.hidden = !item.textContent.toLowerCase().includes(term); }); });
const stats = { users: 1240, projects: 86, uptime: '99.98%' }; document.querySelector('[data-users]').textContent = stats.users; document.querySelector('[data-projects]').textContent = stats.projects; document.querySelector('[data-uptime]').textContent = stats.uptime;
Timers
Schedule code with setTimeout and setInterval.
console.log('Banner shown'); setTimeout(() => { console.log('Banner hidden after 2 seconds'); }, 2000);
let saveCount = 0; const intervalId = setInterval(() => { saveCount++; console.log(`Auto-save ${saveCount}`); if (saveCount >= 3) { clearInterval(intervalId); console.log('Stop auto-save checks'); } }, 500);
const redirectId = setTimeout(() => { console.log('Redirect to billing page'); }, 3000); console.log('Redirect scheduled'); clearTimeout(redirectId); console.log('Redirect canceled');
let secondsLeft = 3; const countdownId = setInterval(() => { console.log(`Refreshing in ${secondsLeft}...`); secondsLeft--; if (secondsLeft < 0) { clearInterval(countdownId); console.log('Refresh now'); } }, 1000);
Async / Await
Write asynchronous code that reads like synchronous code.
function saveDraft(title) { return new Promise(resolve => { setTimeout(() => { resolve({ id: 101, title, savedAt: '10:30' }); }, 600); }); } console.log('Saving draft...'); saveDraft('Homepage hero copy').then(result => { console.log('Saved:', result.title, result.savedAt); });
const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); async function publishArticle() { console.log('1. Saving content'); await wait(300); console.log('2. Generating preview'); await wait(300); console.log('3. Article published'); } publishArticle();
const waitFor = (label, ms) => new Promise(resolve => setTimeout(() => resolve(label), ms)); async function loadDashboard() { const [stats, messages, alerts] = await Promise.all([ waitFor('stats', 400), waitFor('messages', 250), waitFor('alerts', 500) ]); console.log('Loaded:', stats, messages, alerts); } loadDashboard();
async function loadProfile(shouldFail) { console.log('Loading profile...'); try { if (shouldFail) { throw new Error('Network temporarily unavailable'); } return { name: 'Daria', role: 'Editor' }; } catch (err) { console.log(`Error: ${err.message}`); return null; } finally { console.log('Hide loading spinner'); } } loadProfile(false).then(profile => console.log(profile));
Working with APIs
Fetch real data from the internet using fetch().
async function loadPost() { const response = await fetch('https://jsonplaceholder.typicode.com/posts/1'); const post = await response.json(); console.log('Title:', post.title); console.log('Preview:', post.body.slice(0, 40) + '...'); } loadPost();
async function loadFeaturedPosts() { const ids = [1, 2, 3]; const posts = await Promise.all( ids.map(id => fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(res => res.json()) ) ); posts.forEach(post => console.log(post.id, post.title)); } loadFeaturedPosts();
async function sendFeedback() { const response = await fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Adrian', message: 'Editor feels fast and simple.' }) }); const result = await response.json(); console.log('Saved with id:', result.id); } sendFeedback();
async function loadSafe() { try { const response = await fetch('https://jsonplaceholder.typicode.com/posts/9999'); if (!response.ok) { throw new Error(`Request failed with ${response.status}`); } const data = await response.json(); console.log(data); } catch (error) { console.log('Handled error:', error.message); } } loadSafe();
Ready to practice?
Open the editor and try practical examples for logic, data, UI interactions, timing, async flows, and API work. No setup, no install.
All examples run instantly · No account needed · Free forever