URL и URLSearchParams
Зачем нужно
URL API и URLSearchParams — встроенные инструменты для безопасной работы с URL-адресами и query-параметрами. Вместо ручного склеивания строк (которое ломается на спецсимволах) — надёжный API с автоматическим кодированием.
Где используется
- Построение URL для API-запросов с параметрами
- Парсинг текущего URL (извлечение параметров)
- Роутинг в SPA
- Формирование ссылок для share/redirect
Структура URL
https://user:pass@www.example.com:8080/path/page?q=search&page=2#section
protocol: https:
username: user
password: pass
hostname: www.example.com
port: 8080
host: www.example.com:8080
pathname: /path/page
search: ?q=search&page=2
hash: #section
origin: https://www.example.com:8080
href: полный URL
URL API
// === Создание URL ===
const url = new URL('https://example.com/api/search');
url.searchParams.set('q', 'javascript');
url.searchParams.set('page', '2');
console.log(url.toString());
// https://example.com/api/search?q=javascript&page=2
// === Парсинг URL ===
const url = new URL('https://example.com:8080/api/users?role=admin&active=true#section');
url.protocol; // 'https:'
url.hostname; // 'example.com'
url.port; // '8080'
url.pathname; // '/api/users'
url.search; // '?role=admin&active=true'
url.hash; // '#section'
url.origin; // 'https://example.com:8080'
// === Относительные URL ===
const base = new URL('https://example.com/api/v1/');
const users = new URL('users', base); // https://example.com/api/v1/users
const abs = new URL('/other', base); // https://example.com/other
// === Изменение URL ===
const url = new URL('https://example.com/old');
url.pathname = '/new';
url.searchParams.set('key', 'value');
console.log(url.href); // https://example.com/new?key=value
// === Текущий URL страницы ===
const current = new URL(window.location.href);
console.log(current.pathname);
console.log(current.searchParams.get('q'));
URLSearchParams
// === Создание ===
const params = new URLSearchParams();
params.set('q', 'javascript');
params.set('page', '2');
params.set('sort', 'date');
console.log(params.toString()); // q=javascript&page=2&sort=date
// Из строки
const params = new URLSearchParams('q=javascript&page=2');
// Из объекта
const params = new URLSearchParams({
q: 'javascript',
page: '2',
sort: 'date',
});
// Из текущего URL
const params = new URLSearchParams(window.location.search);
// === Чтение ===
params.get('q'); // 'javascript'
params.get('missing'); // null
params.has('q'); // true
params.getAll('tag'); // ['js', 'web'] (если несколько значений)
// === Изменение ===
params.set('page', '3'); // Заменить значение
params.append('tag', 'js'); // Добавить (может быть несколько)
params.append('tag', 'web');
params.delete('sort'); // Удалить
params.sort(); // Отсортировать по имени
// === Итерация ===
for (const [key, value] of params) {
console.log(`${key} = ${value}`);
}
// В объект
const obj = Object.fromEntries(params.entries());
// { q: 'javascript', page: '3', tag: 'web' }
// Внимание: при нескольких одинаковых ключах сохранится только последний
// В массив
const arr = [...params.entries()];
// [['q', 'javascript'], ['page', '3'], ['tag', 'js'], ['tag', 'web']]
Кодирование URL
// URLSearchParams автоматически кодирует спецсимволы
const params = new URLSearchParams();
params.set('q', 'привет мир & more');
console.log(params.toString());
// q=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82+%D0%BC%D0%B8%D1%80+%26+more
// === Ручное кодирование (когда нужно) ===
encodeURIComponent('привет мир & more');
// '%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80%20%26%20more'
decodeURIComponent('%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82');
// 'привет'
// encodeURI — кодирует URL целиком (не трогает :, /, ?, #, &, =)
encodeURI('https://example.com/путь?q=привет');
// 'https://example.com/%D0%BF%D1%83%D1%82%D1%8C?q=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82'
// encodeURIComponent — кодирует значение параметра (кодирует ВСЕ спецсимволы)
encodeURIComponent('a=1&b=2');
// 'a%3D1%26b%3D2'
Практические примеры
// === Построение URL для API ===
function buildApiUrl(endpoint, params = {}) {
const url = new URL(endpoint, 'https://api.example.com');
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
url.searchParams.set(key, String(value));
}
});
return url.toString();
}
buildApiUrl('/users', { page: 2, limit: 10, role: 'admin' });
// 'https://api.example.com/users?page=2&limit=10&role=admin'
// === Обновление URL без перезагрузки (SPA) ===
function updateQueryParam(key, value) {
const url = new URL(window.location.href);
if (value) {
url.searchParams.set(key, value);
} else {
url.searchParams.delete(key);
}
history.pushState(null, '', url.toString());
}
// Пользователь ввёл в поиск → URL обновляется
updateQueryParam('q', 'javascript');
// URL: /search?q=javascript
// === Парсинг параметров при загрузке страницы ===
function getSearchParams() {
return Object.fromEntries(
new URLSearchParams(window.location.search).entries()
);
}
// URL: /products?category=electronics&sort=price&page=2
const { category, sort, page } = getSearchParams;
Частые ошибки
- Ручное склеивание —
url + '?q=' + valueломается на спецсимволах (&, =, пробелы) encodeURIвместоencodeURIComponent— encodeURI не кодирует &, =, ? → параметры ломаются- Забывают
toString—params.setничего не возвращает, нуженparams.toString() Object.fromEntriesс дубликатами — множественные параметры (tag=a&tag=b) теряются- Нет проверки
null—params.get('x')возвращаетnull, неundefined
Практика
- Распарсить URL
https://shop.com/products?category=phones&brand=apple&page=2— извлечь все параметры - Построить URL для API-запроса с фильтрами из объекта
- Реализовать синхронизацию фильтров с URL (query params ←→ состояние)
- Обработать URL с кириллицей и спецсимволами
Связанные темы
- HTTP протокол — URL как часть HTTP-запроса
- Роутинг в SPA — URL-параметры в роутинге
- Клиент-серверное взаимодействие — построение запросов