Пошук уроків, статей та іншого контенту
Розбиратимете URL, параметри запиту та фрагмент сторінки через URL і URLSearchParams.
URL — це адреса ресурсу. У браузері URL може містити не лише протокол і домен, а й шлях, параметри запиту та фрагмент сторінки.
Наприклад:
https://example.com:8080/products/42?category=books&sort=price#reviewsОсновні частини URL:
https — протокол;
example.com — домен;
8080 — порт;
/products/42 — шлях;
?category=books&sort=price — параметри запиту;
#reviews — фрагмент сторінки.
Параметри запиту зазвичай передають дані серверу або JavaScript-програмі. Фрагмент указує на певну частину вже завантаженої сторінки.
URLДля роботи з адресами в JavaScript використовується вбудований об’єкт URL.
const address = new URL(
"https://example.com:8080/products/42?category=books&sort=price#reviews"
);
console.log(address.protocol); // "https:"
console.log(address.hostname); // "example.com"
console.log(address.port); // "8080"
console.log(address.pathname); // "/products/42"
console.log(address.search); // "?category=books&sort=price"
console.log(address.hash); // "#reviews"
console.log(address.href); // повний URLВластивість host містить домен разом із портом:
console.log(address.host); // "example.com:8080"Властивість origin містить протокол, домен і порт:
console.log(address.origin); // "https://example.com:8080"Абсолютний URL містить повну адресу:
const absoluteUrl = new URL("https://example.com/catalog");Відносний URL можна створити лише разом із базовою адресою:
const productUrl = new URL("/products/42", "https://example.com");
console.log(productUrl.href); // "https://example.com/products/42"Це корисно, коли адреси формуються на основі поточного документа або API-адреси.
const imageUrl = new URL("images/logo.svg", "https://example.com/assets/");
console.log(imageUrl.href); // "https://example.com/assets/images/logo.svg"Якщо передати некоректну адресу без бази, JavaScript згенерує помилку TypeError:
// const invalidUrl = new URL("/products/42"); // TypeErrorПараметри запиту розташовані після символу ?.
/products?category=books&sort=price&page=2У цьому прикладі є три параметри:
category зі значенням books;
sort зі значенням price;
page зі значенням 2.
Параметри запиту зберігаються в об’єкті URLSearchParams, доступному через властивість searchParams.
const url = new URL(
"https://example.com/products?category=books&sort=price&page=2"
);
const params = url.searchParams;
console.log(params.get("category")); // "books"
console.log(params.get("sort")); // "price"
console.log(params.get("page")); // "2"Усі значення параметрів є рядками. Якщо значення потрібно використовувати як число, його треба перетворити:
const page = Number(params.get("page"));
console.log(page + 1); // 3Метод has() перевіряє, чи існує параметр:
const url = new URL("https://example.com/products?page=2");
console.log(url.searchParams.has("page")); // true
console.log(url.searchParams.has("category")); // falseЦе відрізняється від перевірки значення. Параметр може існувати, але мати порожній рядок:
const url = new URL("https://example.com/search?q=");
console.log(url.searchParams.has("q")); // true
console.log(url.searchParams.get("q")); // ""Якщо параметра немає, get() повертає null. Для встановлення значення за замовчуванням зручно використовувати оператор ??:
const url = new URL("https://example.com/products");
const page = Number(url.searchParams.get("page") ?? "1");
const sort = url.searchParams.get("sort") ?? "popular";
console.log(page); // 1
console.log(sort); // "popular"Оператор ?? використовує праве значення лише тоді, коли ліве дорівнює null або undefined.
Метод set() додає параметр або замінює його значення:
const url = new URL("https://example.com/products");
url.searchParams.set("category", "books");
url.searchParams.set("page", "2");
console.log(url.href);
// https://example.com/products?category=books&page=2Якщо параметр уже існує, set() замінює його:
const url = new URL("https://example.com/products?page=1");
url.searchParams.set("page", "2");
console.log(url.search); // "?page=2"Метод append() додає ще одне значення з таким самим ім’ям:
const params = new URLSearchParams();
params.append("tag", "javascript");
params.append("tag", "browser");
console.log(params.toString());
// "tag=javascript&tag=browser"Метод delete() видаляє всі параметри з указаним ім’ям:
const url = new URL(
"https://example.com/products?category=books&page=2"
);
url.searchParams.delete("page");
console.log(url.href);
// https://example.com/products?category=booksЯкщо параметр повторюється, get() повертає лише перше значення:
const url = new URL(
"https://example.com/products?tag=javascript&tag=browser"
);
console.log(url.searchParams.get("tag")); // "javascript"
console.log(url.searchParams.getAll("tag")); // ["javascript", "browser"]Для таких параметрів, як фільтри, категорії або ідентифікатори, потрібно використовувати getAll().
URLSearchParams підтримує перебір за допомогою for...of:
const params = new URLSearchParams(
"category=books&page=2&tag=javascript&tag=browser"
);
for (const [name, value] of params) {
console.log(`${name}: ${value}`);
}Результат:
category: books
page: 2
tag: javascript
tag: browserТакож доступні методи:
keys() — імена параметрів;
values() — значення параметрів;
entries() — пари [ім’я, значення].
const params = new URLSearchParams("page=2&sort=price");
console.log([...params.keys()]); // ["page", "sort"]
console.log([...params.values()]); // ["2", "price"]
console.log([...params.entries()]);
// [["page", "2"], ["sort", "price"]]Метод sort() сортує параметри за іменами:
const params = new URLSearchParams("sort=price&category=books");
params.sort();
console.log(params.toString());
// "category=books&sort=price"Параметри URL не повинні містити необроблені пробіли, кирилицю та спеціальні символи. URLSearchParams автоматично кодує такі значення.
const params = new URLSearchParams();
params.set("query", "JavaScript у браузері");
params.set("symbol", "a & b");
console.log(params.toString());
// query=JavaScript+%D1%83+%D0%B1%D1%80%D0%B0%D1%83%D0%B7%D0%B5%D1%80%D1%96&symbol=a+%26+bРозкодовані значення можна отримати через get():
console.log(params.get("query")); // "JavaScript у браузері"
console.log(params.get("symbol")); // "a & b"У більшості випадків не потрібно вручну викликати encodeURIComponent(), якщо ви працюєте з URLSearchParams.
const url = new URL("https://example.com/search");
url.searchParams.set("q", "ноутбук 15 дюймів");
console.log(url.href);
// URL містить безпечно закодоване значення параметраПоточна адреса доступна через window.location.
console.log(window.location.href); // повна адреса
console.log(window.location.pathname); // шлях
console.log(window.location.search); // параметри із символом ?
console.log(window.location.hash); // фрагмент із символом #Для зручної роботи всієї адреси можна створити об’єкт URL:
const currentUrl = new URL(window.location.href);
const query = currentUrl.searchParams.get("q");
const section = currentUrl.hash.slice(1);
console.log(query);
console.log(section);Для поточного документа є коротший варіант:
const currentUrl = new URL(window.location);
console.log(currentUrl.href);Нехай сторінка відкривається за адресою:
/products?category=books&page=2&inStock=trueJavaScript може прочитати параметри та підготувати стан каталогу:
const url = new URL(window.location.href);
const params = url.searchParams;
const filters = {
category: params.get("category") ?? "all",
page: Number(params.get("page") ?? "1"),
inStock: params.get("inStock") === "true",
};
console.log(filters);
// { category: "books", page: 2, inStock: true }Важливо явно перетворювати типи. Наприклад, рядок "false" є істинним значенням у JavaScript:
console.log(Boolean("false")); // trueТому для логічного параметра краще використовувати точне порівняння:
const inStock = params.get("inStock") === "true";Фрагмент розташований після символу #:
https://example.com/docs#installationЙого можна отримати через hash:
const url = new URL("https://example.com/docs#installation");
console.log(url.hash); // "#installation"Щоб отримати лише значення без символу #, можна скористатися slice():
const fragment = url.hash.slice(1);
console.log(fragment); // "installation"Якщо на сторінці є елемент з відповідним id, браузер може прокрутити сторінку до нього:
<h2 id="installation">Встановлення</h2>https://example.com/docs#installationФрагмент не надсилається серверу в HTTP-запиті. Він обробляється браузером і доступний JavaScript через window.location.hash.
Коли користувач переходить між фрагментами сторінки, виникає подія hashchange:
window.addEventListener("hashchange", () => {
const section = window.location.hash.slice(1);
console.log(`Активний розділ: ${section}`);
});Змінити фрагмент можна через location.hash:
window.location.hash = "reviews";Браузер оновить адресу, наприклад:
https://example.com/product#reviewsМетоди history.pushState() і history.replaceState() дають змогу змінити URL без нового завантаження документа.
pushState()pushState() додає новий запис до історії браузера:
const url = new URL(window.location.href);
url.searchParams.set("page", "2");
history.pushState({}, "", url);
console.log(window.location.href);Після цього користувач може натиснути кнопку «Назад» і повернутися до попереднього URL.
replaceState()replaceState() замінює поточний запис історії:
const url = new URL(window.location.href);
url.searchParams.set("sort", "price");
history.replaceState({}, "", url);Цей метод доречний, коли не потрібно створювати додатковий крок у навігації, наприклад для синхронізації службового параметра.
Обидва методи змінюють адресу, але самі по собі не повідомляють програмі про зміну стану. Стан інтерфейсу потрібно оновлювати окремо.
Нижче наведено повний приклад для браузера. Форма бере пошуковий запит із URL, а після відправлення записує його в параметр q без перезавантаження сторінки.
<!doctype html>
<html lang="uk">
<head>
<meta charset="UTF-8">
<title>Пошук</title>
</head>
<body>
<form id="search-form">
<label>
Пошук:
<input id="search-input" name="q" type="search">
</label>
<button type="submit">Знайти</button>
<button id="clear-button" type="button">Очистити</button>
</form>
<p id="status"></p>
<script>
const form = document.querySelector("#search-form");
const input = document.querySelector("#search-input");
const clearButton = document.querySelector("#clear-button");
const status = document.querySelector("#status");
function readSearchFromUrl() {
const url = new URL(window.location.href);
const query = url.searchParams.get("q") ?? "";
input.value = query;
status.textContent = query
? `Результати для: ${query}`
: "Введіть пошуковий запит";
}
form.addEventListener("submit", (event) => {
event.preventDefault();
const url = new URL(window.location.href);
const query = input.value.trim();
if (query) {
url.searchParams.set("q", query);
} else {
url.searchParams.delete("q");
}
history.pushState({}, "", url);
readSearchFromUrl();
});
clearButton.addEventListener("click", () => {
input.value = "";
const url = new URL(window.location.href);
url.searchParams.delete("q");
history.pushState({}, "", url);
readSearchFromUrl();
});
window.addEventListener("popstate", readSearchFromUrl);
readSearchFromUrl();
</script>
</body>
</html>У цьому прикладі:
new URL(window.location.href) створює змінювану копію поточної адреси.
searchParams.get("q") читає пошуковий запит.
set() додає або змінює параметр.
delete() прибирає порожній параметр.
pushState() оновлює URL без перезавантаження.
popstate дає змогу реагувати на переходи кнопками «Назад» і «Вперед».
URLSearchParams можна створити з об’єкта:
const params = new URLSearchParams({
category: "books",
page: "2",
sort: "price",
});
console.log(params.toString());
// "category=books&page=2&sort=price"Це зручно для побудови URL:
const params = new URLSearchParams({
q: "frontend",
page: "1",
});
const url = `https://example.com/search?${params}`;
console.log(url);
// https://example.com/search?q=frontend&page=1Однак масив як значення буде перетворено на рядок із комами:
const params = new URLSearchParams({
tags: ["javascript", "browser"],
});
console.log(params.toString());
// "tags=javascript%2Cbrowser"Якщо сервер очікує повторюваний параметр tags, використовуйте append():
const params = new URLSearchParams();
for (const tag of ["javascript", "browser"]) {
params.append("tag", tag);
}
console.log(params.toString());
// "tag=javascript&tag=browser"URL часто формується з даних користувача, тому важливо правильно кодувати параметри й перевіряти адреси.
URLSearchParams безпечно кодує значення параметрів:
const url = new URL("https://example.com/search");
url.searchParams.set("q", "a & b");
console.log(url.href);Але не слід без перевірки підставляти довільні значення користувача в href, src або навігаційні адреси. Особливо обережно потрібно працювати з URL, які можуть містити протоколи javascript: або data:.
Якщо програма дозволяє користувачу ввести адресу для переходу, перевіряйте протокол:
function isSafeHttpUrl(value) {
try {
const url = new URL(value);
return url.protocol === "http:" || url.protocol === "https:";
} catch {
return false;
}
}
console.log(isSafeHttpUrl("https://example.com")); // true
console.log(isSafeHttpUrl("javascript:alert(1)")); // falseНебезпечно та незручно складати параметри конкатенацією:
// Поганий варіант
const query = "JavaScript у браузері";
const url = "/search?q=" + query;Пробіли, &, # та інші символи можуть зламати адресу. Використовуйте URLSearchParams:
const params = new URLSearchParams();
params.set("q", "JavaScript у браузері");
const url = `/search?${params}`;
console.log(url);get()const url = new URL("https://example.com/products?page=2");
const page = url.searchParams.get("page");
console.log(page + 1); // "21"get() повертає рядок. Перетворюйте його на число:
const page = Number(url.searchParams.get("page"));
console.log(page + 1); // 3get() для повторюваних параметрівconst params = new URLSearchParams("tag=js&tag=css");
console.log(params.get("tag")); // "js"Для отримання всіх значень використовуйте getAll():
console.log(params.getAll("tag")); // ["js", "css"]? і #Властивість search містить символ ?, а hash — символ #:
const url = new URL("https://example.com/page?q=test#top");
console.log(url.search); // "?q=test"
console.log(url.hash); // "#top"Якщо потрібне лише значення фрагмента, приберіть перший символ:
const fragment = url.hash.slice(1);
console.log(fragment); // "top"pushState() і перезавантаженнямhistory.pushState() змінює адресу, але не завантажує сторінку заново й не викликає автоматично логіку обробки нового URL. Після його виклику потрібно самостійно оновити інтерфейс.
Об’єкт URL розбирає адресу на протокол, домен, шлях, параметри та фрагмент.
URLSearchParams призначений для читання і зміни параметрів запиту.
get() повертає одне значення, а getAll() — усі значення параметра.
set() додає або замінює параметр, append() додає повторюване значення, delete() видаляє параметр.
Значення параметрів завжди читаються як рядки, тому числа та логічні значення потрібно перетворювати явно.
hash містить фрагмент сторінки після #.
pushState() і replaceState() дають змогу змінювати URL без перезавантаження документа.
Для безпечного кодування параметрів використовуйте URLSearchParams, а зовнішні адреси перевіряйте перед навігацією.