Skip to content
UNASPACE

JavaScript

This content is for Frontend. Switch to the latest version for up-to-date documentation.

JavaScript is a versatile, high-level, and interpreted programming language. In the context of frontend development, it is the “brain” of the web page, enabling interactivity beyond static HTML and CSS.

YearMilestone
1995Brendan Eich creates JavaScript at Netscape in about 10 days; ships in Navigator.
1995The name changes from Mocha to LiveScript, then to JavaScript for marketing.
1996Microsoft introduces JScript in Internet Explorer.
1997ECMAScript 1 is standardized by Ecma International as a vendor-neutral spec.
1999ECMAScript 3 adds regex, try/catch, and more.
2009ES5 arrives; Node.js brings JavaScript to the server.
2015ES2015 (ES6) adds let/const, classes, modules, and arrow functions.
2016+Yearly ECMAScript releases add async/await, BigInt, optional chaining, and more.
TodayJavaScript powers the browser and broader platforms, from web apps to server-side and tooling workflows.

Despite the similar names, JavaScript and Java are different languages with different goals and ecosystems.

TopicJavaScriptJava
Primary useWeb, frontend, and full-stack (Node.js)Backend, Android, enterprise apps
Type systemDynamically typedStatically typed
RuntimeBrowser engine or Node.jsJVM (Java Virtual Machine)
Syntax styleC-like, flexibleC-like, class-based
CompilationInterpreted/JITCompiled to bytecode

Why the similar names?

  • Netscape renamed LiveScript to JavaScript in 1995 for marketing, riding the popularity of Java.
  • The name similarity does not imply shared code or compatibility.

JavaScript can run in multiple environments, not just the browser.

  • Web browsers: Chrome (V8), Firefox (SpiderMonkey), Safari (JavaScriptCore).
  • Server-side: Node.js, Deno, Bun.
  • Desktop apps: Electron, Tauri (JavaScript/TypeScript with native shells).
  • Mobile apps: React Native, NativeScript.
  • Edge/Serverless: Cloudflare Workers, Vercel Edge Functions, AWS Lambda.
RuntimeFocusHighlights
Node.jsServer-side and toolingHuge ecosystem (npm), stable, widely used
DenoSecure runtime with modern defaultsBuilt-in TypeScript, permissions-based security
BunFast runtime and toolingHigh performance, built-in bundler and test runner

To master JavaScript, it is crucial to distinguish between the language itself (ECMAScript) and the Web APIs provided by the browser environment.

Part 1: Language Fundamentals (ECMAScript)

Section titled “Part 1: Language Fundamentals (ECMAScript)”

These concepts are the core of JavaScript. They work the same way whether you are running code in a browser, on a server (Node.js), or in other environments.

Variables store data. Modern JavaScript uses let and const.

  • const: For values that won’t be reassigned. (Default choice).
  • let: For values that will be reassigned.
  • var: Legacy variable declaration. Avoid using it due to hoisting and lack of block scope.
const birthYear = 1995; // Cannot be changed
let age = 30; // Can be changed
age = 31;
if (true) {
let blockScoped = 'I only exist here';
var functionScoped = 'I leak out of this block';
}
// console.log(blockScoped); // ReferenceError
console.log(functionScoped); // works

JavaScript has 7 primitive types and an Object type.

  • Primitives: String, Number, Boolean, null, undefined, Symbol, BigInt.
  • Objects: Objects, Arrays, Functions.
const name = 'Alice'; // String
const total = 42; // Number
const isStudent = true; // Boolean
let data = null; // null (intentional empty value)
let result; // undefined (not yet assigned)

Functions are blocks of code designed to perform a particular task.

  • Function Declaration: Hoisted, can be called before they are defined.
  • Function Expression: Not hoisted.
  • Arrow Functions: Concise syntax, useful for callbacks. Note: They do not have their own this.
// Declaration
function greet(name) {
return `Hello, ${name}!`;
}
// Arrow Function
const multiply = (a, b) => a * b;
// Higher-Order Function (takes another function as argument)
[1, 2, 3].forEach((num) => console.log(num));

Arrays are used to store lists of data.

Common methods:

  • map(): Transforms every element, returns a new array.
  • filter(): Returns a new array with elements that pass a test.
  • reduce(): Aggregates the array into a single value.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2); // [2, 4, 6, 8, 10]
const evens = numbers.filter((n) => n % 2 === 0); // [2, 4]
const sum = numbers.reduce((acc, current) => acc + current, 0); // 15
// Useful for checking conditions
const hasLargeNum = numbers.some((n) => n > 10); // false
const allPositive = numbers.every((n) => n > 0); // true

Strings in JavaScript are immutable, meaning methods return a new string rather than modifying the original.

  • Template Literals: Use backticks (`) for interpolation and multi-line strings.
  • Methods: trim(), includes(), split(), slice().
const str = ' JavaScript is Awesome! ';
console.log(str.trim()); // "JavaScript is Awesome!"
console.log(str.includes('Script')); // true
console.log(str.toLowerCase()); // " javascript is awesome! "
const words = str.trim().split(' '); // ["JavaScript", "is", "Awesome!"]
const firstWord = str.trim().slice(0, 10); // "JavaScript"

Objects are used to store keyed collections. Classes (ES6) are syntactic sugar over prototypal inheritance.

// Object Literal
const user = {
name: 'John',
greet() {
console.log(`Hello, I'm ${this.name}`);
},
};
// Class (Template for objects)
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog('Mitzie');
d.speak(); // "Mitzie barks."

JavaScript is single-threaded, meaning it can only do one thing at a time. Asynchronous patterns allow it to handle long-running tasks (like fetching data) without freezing the UI.

  • Promises: Represents a value that will be available in the future.
  • Async/Await: Modern, readable way to handle Promises.
// Using Promises
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('Data loaded!'), 1000);
});
};
// Using Async/Await
async function displayData() {
console.log('Loading...');
const result = await fetchData();
console.log(result); // "Data loaded!"
}

JavaScript can compare values in two main ways:

  • Strict equality (===): Compares value and type. Prefer this.
  • Loose equality (==): Allows type coercion, which can be surprising.
0 == '0'; // true (coerces string to number)
0 === '0'; // false (different types)
null == undefined; // true
null === undefined; // false

In conditions, JavaScript converts values to true or false.

  • Falsy: false, 0, -0, 0n, '', null, undefined, NaN
  • Truthy: Everything else (including [], {}, and non-empty strings)
if ('0') console.log('This runs'); // '0' is truthy
if ([]) console.log('This also runs'); // empty array is truthy

Destructuring makes it easy to unpack values from arrays or objects.

const user = { name: 'Ari', role: 'admin' };
const { name, role } = user;
const nums = [10, 20, 30];
const [first, ...rest] = nums; // rest = [20, 30]
const merged = { ...user, active: true };

Modules let you split code across files with clear imports/exports.

utils.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './utils.js';
console.log(add(2, 3));

12. Module Flavors (CommonJS vs ES Modules)

Section titled “12. Module Flavors (CommonJS vs ES Modules)”

JavaScript supports multiple module systems depending on the runtime and tooling.

CommonJS (CJS)

  • Default in older Node.js projects.
  • Uses require() and module.exports.
math.cjs
function add(a, b) {
return a + b;
}
module.exports = { add };
// main.cjs
const { add } = require('./math.cjs');
console.log(add(2, 3));

ES Modules (ESM)

  • Standardized module system for JavaScript.
  • Uses import / export.
math.mjs
export function add(a, b) {
return a + b;
}
// main.mjs
import { add } from './math.mjs';
console.log(add(2, 3));

UMD (Universal Module Definition)

  • Older pattern for libraries that run in both browsers and Node.js.
  • Usually generated by bundlers rather than written by hand.

AMD (Asynchronous Module Definition)

  • Used by older browser loaders (like RequireJS).
  • Largely replaced by ESM and bundlers.

Notes:

  • Node.js supports ESM when "type": "module" is set in package.json, or with .mjs files.
  • CJS uses synchronous loading; ESM is designed for static analysis and tree-shaking.

Browser APIs are tools provided by the browser environment. These are not part of the core JavaScript language, but they are accessible via JavaScript when running in a browser.

The DOM is a structural representation of the HTML document. JavaScript uses it to change content and styles.

// Selecting elements
const title = document.querySelector('h1');
const buttons = document.querySelectorAll('.btn');
// Modifying content and style
title.textContent = 'New Title';
title.style.color = 'blue';
// Creating and Appending
const newDiv = document.createElement('div');
newDiv.innerHTML = '<p>Newly created paragraph</p>';
document.body.appendChild(newDiv);

Events allow you to make the page interactive by responding to user actions.

const btn = document.querySelector('#submit');
btn.addEventListener('click', (event) => {
console.log('Button clicked!');
console.log('Event details:', event);
});

The modern way to make network requests (AJAX).

async function getUser() {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/users/1',
);
if (!response.ok) throw new Error('User not found');
const data = await response.json();
console.log(data.login);
} catch (error) {
console.error('Error fetching data:', error);
}
}

The JSONPlaceholder API is a fake online REST API for testing. It does not persist changes, but it returns realistic responses.

Base URL: https://jsonplaceholder.typicode.com

const BASE_URL = 'https://jsonplaceholder.typicode.com';
// CREATE (POST)
async function createPost() {
const response = await fetch(`${BASE_URL}/posts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Hello Fetch',
body: 'Learning CRUD with fetch()',
userId: 1,
}),
});
if (!response.ok) throw new Error('Failed to create post');
return response.json();
}
// READ (GET)
async function getPost(postId) {
const response = await fetch(`${BASE_URL}/posts/${postId}`);
if (!response.ok) throw new Error('Post not found');
return response.json();
}
// UPDATE (PUT)
async function updatePost(postId) {
const response = await fetch(`${BASE_URL}/posts/${postId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: postId,
title: 'Updated Title',
body: 'Updated body content',
userId: 1,
}),
});
if (!response.ok) throw new Error('Failed to update post');
return response.json();
}
// PARTIAL UPDATE (PATCH)
async function patchPost(postId) {
const response = await fetch(`${BASE_URL}/posts/${postId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Patched Title',
}),
});
if (!response.ok) throw new Error('Failed to patch post');
return response.json();
}
// DELETE
async function deletePost(postId) {
const response = await fetch(`${BASE_URL}/posts/${postId}`, {
method: 'DELETE',
});
if (!response.ok) throw new Error('Failed to delete post');
return true;
}

Usage example:

async function demoCrud() {
const created = await createPost();
console.log('Created:', created);
const read = await getPost(created.id);
console.log('Read:', read);
const updated = await updatePost(created.id);
console.log('Updated:', updated);
const patched = await patchPost(created.id);
console.log('Patched:', patched);
const deleted = await deletePost(created.id);
console.log('Deleted:', deleted);
}

Notes:

  • Always check response.ok before parsing JSON.
  • PUT replaces the resource; PATCH updates specific fields.
  • JSONPlaceholder responds with mocked data but does not persist changes.

Used to save data in the user’s browser.

  • localStorage: Persists even after the browser is closed.
  • sessionStorage: Persists only for the duration of the page session.
// Saving data
localStorage.setItem('theme', 'dark');
// Retrieving data
const currentTheme = localStorage.getItem('theme');
console.log(currentTheme); // 'dark'

Timers schedule work to happen later or repeatedly.

const timerId = setTimeout(() => {
console.log('Runs once after 1s');
}, 1000);
const intervalId = setInterval(() => {
console.log('Runs every 2s');
}, 2000);
// Stop them
clearTimeout(timerId);
clearInterval(intervalId);

JavaScript runs code on a single thread. The event loop coordinates:

  • Call stack: where synchronous code runs.
  • Task queue: timers, DOM events, network callbacks.
  • Microtask queue: Promise callbacks (then, catch, finally).

Microtasks run before the next task, which is why Promises often resolve sooner than setTimeout with 0ms.


ConceptLayerExamples
Variables/LoopsLanguage (Engine)let, for, if
Logic/MathLanguage (Engine)Math.random(), typeof
DOMBrowser APIdocument.body, window.innerWidth
NetworkBrowser APIfetch(), XMLHttpRequest
TimersBrowser APIsetTimeout(), setInterval()
StorageBrowser APIlocalStorage, IndexedDB
Built with passion by Ngineer Lab