Sign in Get started
Solutions
ComplianceDigital ForensicsAccount SecurityWebsite SecurityWeb OptimizationSEO / GEOBusiness IntelligenceUI / UXStartupsDigital TransformationWhite LabelAI Code AuditAI / MLConsulting & AdvisoryBusiness Strategy
Products
Web HostingVPS HostingSSL CertificatesSiteLock SecurityWebsite BackupEmail Spam FilterOX App Suite360 MonitoringWeebly BuilderSite BuilderSEO (Marketgoo)Account SecurityDomainsAll Products
More
NetworkSecurity AboutCareersContactRoadmapLegal
Guide

JavaScript: a modern introduction

JavaScript is the programming language of the web. Every major browser runs it, and with Node.js it also runs on servers and on your own computer. This guide covers the parts you will use on day one, written the way JavaScript is written today.

HTML, CSS and JavaScript each have one jobHTMLStructure and content:headings, text, formsCSSPresentation: colour,layout, fonts, motionJavaScriptBehaviour: react to clicks,load data, change the pageHTMLStructure and content:headings, text, formsCSSPresentation: colour,layout, fonts, motionJavaScriptBehaviour: react to clicks,load data, change the page
Keep the three apart. A page should still show its content if a script fails to load.

What JavaScript does in a page

When a browser loads a page, it builds a tree of objects from the HTML, called the DOM (Document Object Model). JavaScript can read that tree and change it. That is how a menu opens, a form checks your input, a cart total updates or new posts appear without a page reload.

Where to run it

The browser console is the fastest place to start. Open the developer tools (F12, or right-click and choose Inspect) and pick the Console tab. Type a line and press Enter:

2 + 3
// 5
"Hello, " + "world"
// "Hello, world"
document.title
// the title of the page you are on

In a page, put your code in a file and load it at the end of the head with defer, so it runs after the HTML has been read:

<script src="app.js" defer></script>

On your computer, install Node.js. Pick the LTS (long-term support) release. As of October 2026 that is Node.js 26, which became the active LTS line on 28 October 2026. Node.js 24 is in maintenance and gets security fixes until April 2028. Check your version and run a file like this:

node --version
node hello.js

Variables: const and let

Use const by default. Use let only when the value will be reassigned. Both are limited to the block they are written in, which prevents a whole family of bugs. The older var keyword ignores blocks, so modern code avoids it.

const siteName = "Internetivo";
let visits = 0;
visits = visits + 1;   // fine: let can change

const prices = [12, 30, 8];
prices.push(15);       // fine: the array itself can change
// siteName = "Other"; // error: a const cannot be reassigned

const message = `${siteName} has ${prices.length} prices`;

Note the backticks in the last line. A template literal lets you put values inside a string with ${...}. Compare values with === and !==, which never convert types behind your back.

Functions and arrow functions

A function is a named, reusable piece of code. Arrow functions are a shorter form, handy for small calculations and for passing a function to another one, as reduce does here. Parameters can have default values.

function total(items) {
  return items.reduce((sum, n) => sum + n, 0);
}

const withVat = (amount, rate = 0.19) => amount * (1 + rate);

total([12, 30, 8]);   // 50
withVat(100);         // 119

Selecting elements and handling events

document.querySelector finds the first element that matches a CSS selector. addEventListener runs a function when something happens: a click, a key press, a form submit. Show results inside the page, in an element that screen readers announce, rather than in a pop-up box.

<form id="signup">
  <label for="email">E-mail</label>
  <input id="email" type="email" required>
  <button>Join</button>
  <p id="status" aria-live="polite"></p>
</form>
const form = document.querySelector("#signup");
const status = document.querySelector("#status");

form.addEventListener("submit", (event) => {
  event.preventDefault();
  const email = form.querySelector("#email").value.trim();

  if (!email.includes("@")) {
    status.textContent = "Please enter a full e-mail address.";
    status.classList.add("error");
    return;
  }
  status.textContent = `Thanks, we will write to ${email}.`;
  status.classList.remove("error");
});

Use textContent to put text into the page. It treats the value as plain text, so a user cannot inject HTML. Use classList to switch styles and leave the styling itself to CSS. And keep validating on the server too: browser checks help users but stop no attacker.

Loading data with fetch, async and await

fetch asks a server for data. The answer takes time, so fetch returns a promise, a value that arrives later. Inside an async function, await pauses until it arrives, so the code reads from top to bottom. Wrap it in try and catch, and check response.ok, because fetch does not fail on a 404 or 500 by itself.

async function loadPosts() {
  const list = document.querySelector("#posts");
  try {
    const response = await fetch("/api/posts.json");
    if (!response.ok) {
      throw new Error(`Server replied ${response.status}`);
    }
    const posts = await response.json();
    list.replaceChildren(...posts.map((post) => {
      const item = document.createElement("li");
      item.textContent = post.title;
      return item;
    }));
  } catch (error) {
    list.textContent = "Could not load posts. Please try again.";
    console.error(error);
  }
}

document.querySelector("#load").addEventListener("click", loadPosts);
What happens when a visitor clicks a button that loads dataClickaddEventListenerruns your functionfetch()A request goesto the serverawaitThe code waitsfor the JSON replyUpdate DOMNew text appearswithout a reloadClickaddEventListener runs your functionfetch()A request goes to the serverawaitThe code waits for the JSON replyUpdate DOMNew text appears without a reload
The pattern behind most interactive pages: an event, a request, a wait, then a change to the page.

Modules: split code into files

As a project grows, split it into modules. Each file exports what others may use and imports what it needs:

// prices.js
export function withVat(amount, rate = 0.19) {
  return amount * (1 + rate);
}
// app.js
import { withVat } from "./prices.js";
console.log(withVat(100));
<script type="module" src="app.js"></script>

Module scripts are deferred automatically and run in strict mode, which turns silent mistakes into clear errors. Open the page through a local server rather than straight from the file system; browsers block modules loaded from file:// addresses. A tool such as Vite gives you that server in one command. Our list of developer and designer tools covers it.

Habits that save time

  • Keep the console open while you work. Errors show the file and line number.
  • Use console.log freely, then remove it before you ship.
  • Format code automatically with Prettier and let ESLint flag likely bugs.
  • Learn from the MDN JavaScript Guide, the most reliable free reference.
  • Treat anything from a user or a server as untrusted. The security checklist for web developers explains why.

Common questions

Is JavaScript the same as Java?
No. They share part of a name and some syntax, nothing more. Java is a separate language used mostly for servers and Android apps.
Should I learn TypeScript first?
Learn plain JavaScript first. TypeScript adds types on top of it, and it makes much more sense once you know what it is checking.
Do I still need jQuery?
For new work, no. Everything jQuery made easy, such as selecting elements, events and requests, is now built into the browser.
Which Node.js version should I install?
The release marked LTS on nodejs.org. Newer releases that have not reached LTS yet are for trying new features, not for production.

Do you write JavaScript and want paid work? Getting paid on Internetivo explains how professionals find tasks and get paid for accepted work.