Learn JavaScript

URL - объект для работы с адресами в JavaScript

URL - это встроенный объект для работы с адресами.

Он помогает не склеивать URL вручную строками, а разбирать и собирать адрес через понятные свойства: protocol, hostname, pathname, search, hash и другие.

Чаще всего URL используют, когда нужно:

  • разобрать адрес на отдельные части
  • добавить или изменить параметры запроса
  • собрать URL из базового адреса и относительного пути
  • безопасно подготовить адрес для перехода или запроса
  • проверить, что строка действительно является корректным URL

Синтаксис

Объект создают через new URL().

new URL(url, base)

Где:

  • url - абсолютный или относительный адрес
  • base - необязательный базовый адрес, нужен для относительных URL

Пример с абсолютным адресом:

const url = new URL("https://learn-javascript.ru/catalog?sort=price");

Пример с относительным адресом:

const url = new URL("/catalog", "https://learn-javascript.ru");

Без new использовать URL нельзя.

URL("https://learn-javascript.ru"); // TypeError

Что возвращает URL

new URL() возвращает объект URL.

const url = new URL("https://learn-javascript.ru/catalog");

console.log(url instanceof URL); // true
console.log(url.href); // "https://learn-javascript.ru/catalog"

Сам объект хранит адрес и даёт удобный доступ к его частям.

Если нужно снова получить обычную строку, можно использовать href или toString().

const url = new URL("https://learn-javascript.ru/catalog");

console.log(url.href); // "https://learn-javascript.ru/catalog"
console.log(url.toString()); // "https://learn-javascript.ru/catalog"

Из каких частей состоит URL

Возьмём такой адрес:

const url = new URL("https://learn-javascript.ru:8080/catalog/books?sort=price#reviews");

Теперь его можно разобрать на части:

console.log(url.protocol); // "https:"
console.log(url.host); // "learn-javascript.ru:8080"
console.log(url.hostname); // "learn-javascript.ru"
console.log(url.port); // "8080"
console.log(url.pathname); // "/catalog/books"
console.log(url.search); // "?sort=price"
console.log(url.hash); // "#reviews"

Полный адрес лежит в href.

console.log(url.href);
// "https://learn-javascript.ru:8080/catalog/books?sort=price#reviews"

Свойство origin содержит протокол, домен и порт.

console.log(url.origin); // "https://learn-javascript.ru:8080"

host и hostname - не одно и то же

Эти свойства легко перепутать.

const url = new URL("https://learn-javascript.ru:8080/catalog");

console.log(url.host); // "learn-javascript.ru:8080"
console.log(url.hostname); // "learn-javascript.ru"

host содержит домен вместе с портом, если порт указан.

hostname содержит только имя хоста без порта.

URL можно изменять через свойства

Свойства объекта URL можно менять, и полный адрес пересоберётся автоматически.

const url = new URL("https://learn-javascript.ru/catalog");

url.pathname = "/products";
url.search = "?page=2";
url.hash = "#top";

console.log(url.href);
// "https://learn-javascript.ru/products?page=2#top"

Это удобнее, чем вручную следить за слешами, вопросительными знаками и решётками.

Можно менять и домен:

const url = new URL("https://learn-javascript.ru/catalog");

url.hostname = "shop.learn-javascript.ru";

console.log(url.href);
// "https://shop.learn-javascript.ru/catalog"

Относительный URL и базовый адрес

Если адрес относительный, нужно передать второй аргумент base.

const url = new URL("/catalog", "https://learn-javascript.ru");

console.log(url.href); // "https://learn-javascript.ru/catalog"

Без базового адреса относительная строка не будет понятна.

new URL("/catalog"); // TypeError

В браузере в качестве базы часто используют текущий адрес страницы.

const url = new URL("/catalog", window.location.origin);

Если путь не начинается со слеша, он считается относительным к текущему пути базы.

const url = new URL("books", "https://learn-javascript.ru/catalog/");

console.log(url.href); // "https://learn-javascript.ru/catalog/books"

А путь со слешем начинается от корня сайта.

const url = new URL("/books", "https://learn-javascript.ru/catalog/");

console.log(url.href); // "https://learn-javascript.ru/books"

Параметры запроса через searchParams

Самая практичная часть URL - свойство searchParams.

Оно позволяет работать с параметрами после ? не через ручную склейку строк, а через методы.

const url = new URL("https://learn-javascript.ru/search");

url.searchParams.set("q", "javascript");
url.searchParams.set("page", "1");

console.log(url.href);
// "https://learn-javascript.ru/search?q=javascript&page=1"

Получить значение параметра можно через get().

const url = new URL("https://learn-javascript.ru/search?q=javascript&page=1");

console.log(url.searchParams.get("q")); // "javascript"
console.log(url.searchParams.get("page")); // "1"

Проверить наличие параметра можно через has().

const url = new URL("https://learn-javascript.ru/search?q=javascript");

console.log(url.searchParams.has("q")); // true
console.log(url.searchParams.has("page")); // false

Удалить параметр можно через delete().

const url = new URL("https://learn-javascript.ru/search?q=javascript&page=1");

url.searchParams.delete("page");

console.log(url.href);
// "https://learn-javascript.ru/search?q=javascript"

set() и append()

Для параметров важно различать set() и append().

set() устанавливает одно значение и заменяет старое.

const url = new URL("https://learn-javascript.ru/search?q=js");

url.searchParams.set("q", "javascript");

console.log(url.href);
// "https://learn-javascript.ru/search?q=javascript"

append() добавляет ещё одно значение с тем же именем.

const url = new URL("https://learn-javascript.ru/catalog");

url.searchParams.append("tag", "js");
url.searchParams.append("tag", "frontend");

console.log(url.href);
// "https://learn-javascript.ru/catalog?tag=js&tag=frontend"

Это полезно, если сервер ожидает несколько одинаковых параметров.

URL сам кодирует параметры

Если в параметре есть пробелы, русские буквы или специальные символы, searchParams подготовит их для URL.

const url = new URL("https://learn-javascript.ru/search");

url.searchParams.set("q", "уроки javascript");

console.log(url.href);

В строке адреса значение будет закодировано так, чтобы его можно было безопасно передать в URL.

Это одна из причин не собирать параметры вручную:

// Лучше не так
const badUrl = "/search?q=уроки javascript";

Правильнее:

const url = new URL("/search", "https://learn-javascript.ru");

url.searchParams.set("q", "уроки javascript");

hash - часть адреса после

hash хранит фрагмент адреса.

const url = new URL("https://learn-javascript.ru/docs#install");

console.log(url.hash); // "#install"

Фрагмент часто используют для перехода к конкретному блоку страницы.

const url = new URL("https://learn-javascript.ru/docs");

url.hash = "examples";

console.log(url.href);
// "https://learn-javascript.ru/docs#examples"

Можно указывать значение с # или без него. В итоговом адресе решётка будет стоять правильно.

Проверка URL через try…catch

Если строка не похожа на корректный абсолютный URL, new URL() выбросит ошибку.

try {
  const url = new URL("not a url");
  console.log(url.href);
} catch (error) {
  console.log("Некорректный URL");
}

Для относительного адреса можно передать базу:

try {
  const url = new URL("/catalog", "https://learn-javascript.ru");
  console.log(url.href);
} catch (error) {
  console.log("Некорректный URL");
}

Так можно аккуратно проверять адреса, которые пришли от пользователя или из внешних данных.

URL не отправляет запрос

URL только создаёт и разбирает адрес.

Сам по себе объект URL ничего не загружает и не отправляет.

const url = new URL("https://learn-javascript.ru/api/users");

console.log(url.href);

Если нужно сделать сетевой запрос, адрес можно передать в fetch().

const url = new URL("/api/users", window.location.origin);

fetch(url);

Здесь URL отвечает за адрес, а fetch() - за сам запрос.

Когда это полезно

URL особенно удобен, когда адрес нужно не просто хранить строкой, а менять или анализировать.

Например, собрать ссылку на страницу каталога:

function createCatalogUrl(category, page) {
  const url = new URL("/catalog", "https://learn-javascript.ru");

  url.searchParams.set("category", category);
  url.searchParams.set("page", String(page));

  return url.href;
}

console.log(createCatalogUrl("books", 2));
// "https://learn-javascript.ru/catalog?category=books&page=2"

Или получить параметры из текущего адреса страницы:

const currentUrl = new URL(window.location.href);

const page = currentUrl.searchParams.get("page") || "1";
const category = currentUrl.searchParams.get("category") || "all";

console.log(page, category);

Частые ошибки

Вызывать URL без new

const url = URL("https://learn-javascript.ru"); // TypeError

Нужно создавать объект через new URL().

const url = new URL("https://learn-javascript.ru");

Создавать относительный URL без base

const url = new URL("/catalog"); // TypeError

Для относительного адреса нужен базовый адрес.

const url = new URL("/catalog", "https://learn-javascript.ru");

Путать host и hostname

const url = new URL("https://learn-javascript.ru:8080/catalog");

console.log(url.host); // "learn-javascript.ru:8080"
console.log(url.hostname); // "learn-javascript.ru"

Если нужен домен без порта, используйте hostname.

Вручную склеивать параметры

const query = "уроки javascript";
const url = "/search?q=" + query;

Так легко забыть про кодирование специальных символов.

Лучше использовать searchParams.

const url = new URL("/search", "https://learn-javascript.ru");

url.searchParams.set("q", "уроки javascript");

Забывать, что search и hash включают специальные символы

const url = new URL("https://learn-javascript.ru/catalog?page=1#top");

console.log(url.search); // "?page=1"
console.log(url.hash); // "#top"

Если нужен параметр без ?, берите его через searchParams.

console.log(url.searchParams.get("page")); // "1"

Быстрая памятка

  • URL создают через new URL()
  • абсолютный URL можно создать без второго аргумента
  • относительный URL требует базовый адрес base
  • href хранит полный адрес строкой
  • origin хранит протокол, домен и порт
  • host включает порт, hostname не включает порт
  • pathname хранит путь
  • search хранит строку параметров вместе с ?
  • hash хранит фрагмент вместе с #
  • параметры удобнее менять через searchParams
  • searchParams.set() заменяет значение
  • searchParams.append() добавляет ещё одно значение
  • URL помогает собрать адрес, но сам не отправляет запрос

Коротко

URL в JavaScript нужен для безопасной и удобной работы с адресами. Он разбирает строку URL на части, позволяет менять путь, домен, параметры и фрагмент, автоматически пересобирает итоговый адрес и помогает избежать ручной склейки строк там, где легко ошибиться со слешами, ?, & или кодированием символов.