Как декодировать URL в JavaScript (полное руководство)
В JavaScript есть функция decodeURIComponent() для декодирования отдельных компонентов URI и decodeURI() для декодирования URI целиком. Используйте try-catch для обработки некорректных URI. API URL и URLSearchParams предлагают более безопасные способы разбора URL.
decodeURIComponent() — декодирование компонента URI
decodeURIComponent() — основная функция для декодирования URL-кодированных строк в JavaScript. Она декодирует все percent-encoded последовательности, возвращая их к исходным символам. Используйте эту функцию для декодирования значений параметров запроса, сегментов пути или любого отдельного компонента URI.
// Простое декодирование
console.log(decodeURIComponent('hello%20world'));
// "hello world"
console.log(decodeURIComponent('price%3D10%26qty%3D2'));
// "price=10&qty=2"
// Декодирование символов Unicode
console.log(decodeURIComponent('caf%C3%A9'));
// "cafe" (с акцентом)
console.log(decodeURIComponent('%E4%B8%AD%E6%96%87'));
// Китайские иероглифы
// Декодирование значения параметра запроса из URL
const url = 'https://example.com/search?q=C%2B%2B%20%26%20Java';
const params = url.split('?')[1];
const value = params.split('=')[1];
console.log(decodeURIComponent(value));
// "C++ & Java"
decodeURIComponent() декодирует все percent-encoded последовательности, включая те, что соответствуют зарезервированным символам, таким как %2F (/) и %3F (?). Это правильное поведение при работе с отдельными компонентами URI, но оно может привести к проблемам, если применить функцию к URL целиком.
decodeURI() — декодирование URI целиком
decodeURI() декодирует URI целиком, сохраняя его структуру. В отличие от decodeURIComponent(), она не декодирует последовательности, представляющие зарезервированные символы URI, такие как %2F (/), %3F (?), %23 (#) и %26 (&).
// decodeURI сохраняет структуру URI
console.log(decodeURI('https://example.com/my%20page?q=hello%20world'));
// "https://example.com/my page?q=hello world"
// Пробелы декодируются, но /, ? и = сохраняются
// Сравнение с decodeURIComponent для URL целиком
console.log(decodeURIComponent('https%3A%2F%2Fexample.com%2Fpath'));
// "https://example.com/path" — корректно декодирует, если весь URL был закодирован
// decodeURI не декодирует последовательности зарезервированных символов
console.log(decodeURI('path%2Fto%2Ffile'));
// "path%2Fto%2Ffile" — %2F НЕ декодируется, потому что / зарезервирован
console.log(decodeURIComponent('path%2Fto%2Ffile'));
// "path/to/file" — %2F декодируется
Используйте decodeURI(), когда нужно сделать URL более читаемым (например, для отображения) без изменения его структуры. В большинстве же программных сценариев вам понадобится decodeURIComponent(), применяемый к отдельным компонентам.
Обработка некорректных URI
И decodeURI(), и decodeURIComponent() выбрасывают URIError, когда встречают недопустимые percent-encoded последовательности. Это происходит при одиночных знаках процента, неполных последовательностях или недопустимых байтовых последовательностях UTF-8. Всегда оборачивайте операции декодирования в блок try-catch при работе с URL, полученными от пользователя или из внешних источников.
// Эти вызовы выбрасывают URIError: URI malformed
try {
decodeURIComponent('%'); // одиночный процент
} catch (e) {
console.error(e.message); // "URI malformed"
}
try {
decodeURIComponent('%2'); // неполная последовательность
} catch (e) {
console.error(e.message); // "URI malformed"
}
// Функция безопасного декодирования
function safeDecode(str) {
try {
return decodeURIComponent(str);
} catch (e) {
console.warn('Failed to decode:', str);
return str; // в случае ошибки возвращаем исходную строку
}
}
// Исправляем некорректные percent-последовательности перед декодированием
function fixAndDecode(str) {
// Заменяем одиночный % на %25 (закодированный знак процента)
const fixed = str.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');
return decodeURIComponent(fixed);
}
console.log(fixAndDecode('100% complete'));
// "100% complete"
Использование API URL (рекомендуется)
Современные API URL и URLSearchParams предлагают более безопасный и структурированный способ разбора и декодирования URL. Они автоматически выполняют кодирование и декодирование, снижая риск ошибок.
// Разбираем URL и обращаемся к его компонентам (декодируются автоматически)
const url = new URL('https://example.com/path%20here?q=hello%20world&lang=en');
console.log(url.pathname); // "/path here" (декодировано)
console.log(url.search); // "?q=hello%20world&lang=en" (в исходном виде)
// URLSearchParams автоматически декодирует значения параметров
console.log(url.searchParams.get('q')); // "hello world"
console.log(url.searchParams.get('lang')); // "en"
// Перебираем все параметры
for (const [key, value] of url.searchParams) {
console.log(key, '=', value);
}
// q = hello world
// lang = en
// URLSearchParams обрабатывает + как пробел (form encoding)
const formParams = new URLSearchParams('q=hello+world&lang=en');
console.log(formParams.get('q')); // "hello world"
// Построение URL с автоматическим кодированием
const newUrl = new URL('https://example.com/search');
newUrl.searchParams.set('q', 'C++ & Java');
newUrl.searchParams.set('page', '1');
console.log(newUrl.toString());
// "https://example.com/search?q=C%2B%2B+%26+Java&page=1"
Частые ошибки при декодировании
Ошибка 1: декодирование URL целиком с помощью decodeURIComponent(). Это может нарушить структуру URL, если он содержит закодированные зарезервированные символы. %2F в значении параметра превратится в /, что потенциально изменит смысл URL.
Ошибка 2: двойное декодирование. Если строка уже была декодирована один раз, повторное декодирование может дать неожиданный результат или ошибку. Например, строка %2520 сначала декодируется в %20, а затем в пробел. Если вы ожидаете только один уровень кодирования, двойное декодирование испортит данные.
// Проблема двойного декодирования
const encoded = '%2520'; // Это закодированный %20
console.log(decodeURIComponent(encoded)); // "%20" (верно — один уровень)
console.log(decodeURIComponent(decodeURIComponent(encoded))); // " " (двойное декодирование!)
// Проверяем, нужно ли декодировать строку, перед её декодированием
function needsDecoding(str) {
return str !== decodeURIComponent(str);
}
Ошибка 3: игнорирование знака +. decodeURIComponent() не преобразует + в пробелы. Если вы декодируете данные в формате form-urlencoded, нужно сначала заменить + на пробелы или использовать URLSearchParams, который делает это автоматически.
// decodeURIComponent НЕ декодирует + как пробел
console.log(decodeURIComponent('hello+world'));
// "hello+world" (а не "hello world"!)
// Решение: заменяем + перед декодированием
function decodeFormValue(str) {
return decodeURIComponent(str.replace(/\+/g, ' '));
}
console.log(decodeFormValue('hello+world'));
// "hello world"
// Или используем URLSearchParams (обрабатывает + автоматически)
const params = new URLSearchParams('q=hello+world');
console.log(params.get('q'));
// "hello world"