<< Home

Chapter 17: Standard Library Essentials

JavaScript ships with a rich set of built-in objects that form its standard library. These objects handle common needs such as working with numbers, dates, URLs, and data serialization. They are always available in any JavaScript environment, making them essential tools for reliable, portable code.

This chapter explores several of the most widely used core utilities. You will learn how the Number, Math, and BigInt objects help perform calculations and represent numeric data of various sizes. You will also see how the Date object manages time and scheduling, and how Intl provides language-aware formatting for numbers, currencies, and dates. Later sections cover the URL and URLSearchParams interfaces for parsing and manipulating web addresses, and conclude with practical data handling using StructuredClone and JSON.

💡 The standard library is available in every JavaScript environment without imports or external dependencies. It forms the foundation for nearly all higher-level frameworks and APIs.

Although these features are simple in concept, they cover a wide range of use cases from everyday data formatting to advanced web applications. Mastering them ensures your programs remain efficient, portable, and idiomatic across browsers and runtimes.

Number, Math, and BigInt helpers

JavaScript provides several built-in objects for handling numeric data. The Number type represents all standard floating-point and integer values, while BigInt enables safe computation with integers beyond the limits of the 64-bit range. The Math object complements both by offering constants and utility methods for calculations such as rounding, trigonometry, and logarithms.

Because JavaScript’s Number type is based on IEEE 754 double-precision floating-point arithmetic, it can represent extremely large and small values, but may introduce rounding errors in certain decimal operations. BigInt avoids this by representing integers of arbitrary size, though it cannot be mixed directly with regular numbers without explicit conversion.

// Working with Number
let x = 0.1 + 0.2;
console.log(x);                  // 0.30000000000000004

// Using BigInt for large integers
let big = 123456789012345678901234567890n;
console.log(big + 10n);          // 123456789012345678901234567900n

// Math utilities
console.log(Math.round(4.7));    // 5
console.log(Math.max(3, 8, 2));  // 8
console.log(Math.sqrt(9));       // 3
⚠️ Arithmetic between Number and BigInt values is not allowed. You must convert one type to the other explicitly using Number() or BigInt().

In addition to the familiar trigonometric and rounding functions, Math also includes modern methods such as Math.sign(), Math.trunc(), and Math.hypot() for more robust calculations. Constants like Math.PI and Math.E are also provided for convenience.

console.log(Math.sign(-3));     // -1
console.log(Math.trunc(3.9));   // 3
console.log(Math.hypot(3, 4));  // 5
💡 For financial or decimal-precise operations, consider using integer arithmetic (such as counting cents instead of fractional dollars) or a dedicated decimal library to avoid floating-point rounding issues.

Unlike Number values, which are limited to about 15–16 digits of precision, BigInt values are unbounded. This means they can grow to any size that memory allows, making them ideal for tasks that involve very large integers. Examples include cryptographic algorithms such as RSA, where numbers often exceed a thousand bits in length, or precise arithmetic on large datasets where overflow would otherwise occur. Although BigInt operations are slower than those on regular numbers, they maintain exact integer accuracy regardless of magnitude.

Together, Number, Math, and BigInt form the numeric backbone of JavaScript, providing both simplicity and flexibility for numerical computation across all environments.

Date and time basics

JavaScript provides the Date object to represent and manipulate points in time. A Date instance stores a single moment as the number of milliseconds since midnight on January 1, 1970 UTC (the Unix epoch). You can create, format, and modify these values using the object’s constructor and methods.

// Current date and time
let now = new Date();
console.log(now.toString());

// Create specific dates
let d1 = new Date('2028-12-31T23:59:59Z');
let d2 = new Date(2028, 11, 31, 23, 59, 59);  // Months are 0-based

console.log(d1.getFullYear());                // 2028
console.log(d2.getMonth());                   // 11 (December)

Because Date internally stores UTC time, most methods can return either UTC or local values. For instance, getHours() gives the local hour, while getUTCHours() returns the corresponding UTC hour. Timezone handling can therefore differ between systems depending on user settings.

⚠️ The Date API is not fully timezone-aware. For accurate global time calculations, use libraries or newer internationalization APIs such as Intl.DateTimeFormat.

Besides its constructor and getters/setters, Date includes utility methods such as Date.now() (which returns the current time in milliseconds since the epoch) and toISOString() for producing standardized date strings.

console.log(Date.now());  // milliseconds since 1970-01-01
console.log(now.toISOString());      // e.g. "2028-10-29T16:00:00.000Z"
💡 When comparing or sorting dates, use getTime() to compare their numeric millisecond values rather than relying on string forms.

While the Date object covers most everyday needs, modern projects that require consistent time zones, formatting, or calendar arithmetic often use Intl or third-party libraries. These provide more robust handling of locales and cultural variations in date and time representation.

Internationalization

The Intl namespace provides a suite of internationalization features built into JavaScript. It enables programs to format numbers, currencies, dates, and text according to the rules and conventions of different locales without the need for external libraries. This ensures that your output looks correct to users around the world, matching local languages, scripts, and cultural norms.

// Number formatting example
let amount = 1234567.89;
let formatter = new Intl.NumberFormat('en-GB');
console.log(formatter.format(amount));  // "1,234,567.89"

// Currency formatting
let usd = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
let eur = new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' });
console.log(usd.format(99.95));         // "$99.95"
console.log(eur.format(99.95));         // "99,95 €"

The same pattern works for dates and times using Intl.DateTimeFormat. You can specify which components to show, such as weekday, month, or time zone, while letting the system choose regionally appropriate formatting.

// Date formatting
let now = new Date();
let dtFormat = new Intl.DateTimeFormat('fr-FR', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(dtFormat.format(now));  // e.g. "mercredi 29 octobre 2025"
💡 Using Intl avoids the pitfalls of manual string formatting. It automatically applies correct punctuation, separators, and ordering for the chosen locale.

The Intl API also includes Intl.Collator for locale-aware string comparison and sorting, Intl.RelativeTimeFormat for expressions like “3 days ago”, and Intl.ListFormat for joining items with natural conjunctions such as “apples, oranges, and bananas”.

// Relative time
let rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-3, 'day'));  // "3 days ago"

// List formatting
let lf = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
console.log(lf.format(['HTML', 'CSS', 'JavaScript']));  // "HTML, CSS, and JavaScript"
⚠️ The Intl API follows browser and runtime locale data. Some older environments may not include every locale or option, so verify support if targeting embedded or legacy systems.

By leveraging Intl, your applications can easily adapt numeric, monetary, and textual output to diverse audiences, enhancing clarity and professionalism without extra dependencies.

URL and URLSearchParams

Modern JavaScript includes built-in support for working with web addresses through the URL and URLSearchParams classes. These provide a structured way to parse, inspect, and modify URLs without relying on string manipulation. Both are available in browsers and most server environments such as Node.js.

// Create and inspect a URL
let url = new URL('https://example.com:8080/path/page.html?user=robin&debug=true#section2');

console.log(url.protocol);  // "https:"
console.log(url.hostname);  // "example.com"
console.log(url.port);      // "8080"
console.log(url.pathname);  // "/path/page.html"
console.log(url.search);    // "?user=robin&debug=true"
console.log(url.hash);      // "#section2"

You can modify any component directly by setting its corresponding property, and the href updates automatically to reflect the change. This makes the URL object ideal for building and adjusting links dynamically.

url.pathname = '/new/page.html';
url.searchParams.set('debug', 'false');
console.log(url.href);
// "https://example.com:8080/new/page.html?user=robin&debug=false#section2"
💡 The URL object automatically encodes parameters to maintain valid formatting, so you never need to call encodeURIComponent() manually for query strings.

The URLSearchParams interface is designed specifically for handling the query string portion of a URL. It supports adding, deleting, updating, and iterating over parameters, much like a map.

let params = new URLSearchParams('?page=5&sort=desc');

console.log(params.get('page')); // "5"
params.set('filter', 'active');
params.delete('sort');

for (let [key, value] of params) {
  console.log(key, value);
}
// page 5
// filter active

You can also serialize parameters back to a string with toString(), which produces a correctly encoded query segment ready for concatenation or reassignment.

console.log(params.toString()); // "page=5&filter=active"
⚠️ URLSearchParams always encodes keys and values in UTF-8, ensuring consistency across environments. However, duplicate keys are allowed, so use getAll() if a parameter may appear multiple times.

Together, URL and URLSearchParams provide a robust, native alternative to manual parsing. They simplify building APIs, manipulating navigation links, and handling web requests in a standards-compliant way.

StructuredClone() and JSON methods

When copying or transferring data in JavaScript, it is important to distinguish between shallow and deep copies. A shallow copy only duplicates the top level of an object, while nested structures remain shared. The structuredClone() function provides a native deep-cloning mechanism that recursively copies complex objects, including arrays, maps, sets, and even circular references.

let original = { 
  user: 'Robin', 
  data: [1, 2, 3], 
  nested: { key: 'value' } 
};

let copy = structuredClone(original);

console.log(copy.nested === original.nested); // false

This method is particularly useful when you need to safely duplicate data structures without linking references between them. It follows the same structured serialization algorithm used by web workers and postMessage(), which allows it to handle more data types than JSON can, including Map, Set, Blob, and File.

⚠️ structuredClone() cannot clone functions, DOM nodes, or objects with internal platform references such as Window. These will cause an exception if encountered.

Before structuredClone() became available, JSON serialization was the common approach for deep copying. The combination of JSON.stringify() and JSON.parse() converts data into a string and back again, though it supports only plain objects, arrays, numbers, strings, booleans, and null.

let source = { a: 1, b: { c: 2 } };
let clone = JSON.parse(JSON.stringify(source));
console.log(clone.b === source.b);  // false

Beyond cloning, JSON methods are used widely for data storage and network communication. The JSON.stringify() function supports options for indentation and replacer filters, while JSON.parse() can apply a reviver function to transform values during decoding.

// Pretty-printing JSON
let person = { name: 'Alex', age: 30, active: true };
console.log(JSON.stringify(person, null, 2));

// Parsing with a reviver
let text = '{"timestamp": "2028-10-29T16:00:00Z"}';
let data = JSON.parse(text, (key, value) => {
  if (key === 'timestamp') return new Date(value);
  return value;
});
console.log(data.timestamp instanceof Date);  // true
💡 Use structuredClone() for fast, type-safe duplication of in-memory data, and JSON methods for serialization across storage or network boundaries.

Together, these tools cover the two most common needs in modern JavaScript: cloning live objects and encoding structured data for persistence or transfer.