Fitur pencarian katalog toko Budi menghasilkan tautan seperti https://toko.example/katalog?kata=kamus&urut=harga. Karena menyusun tautan itu dengan gabungan string, Budi pernah menulis "?kata=" + kataKunci — dan tautannya rusak begitu pengunjung mencari frasa berisi spasi atau tanda &, misalnya “buku & novel”. Karakter yang punya makna khusus di dalam URL tidak boleh ditempel mentah-mentah ke string. Browser menyediakan dua object bawaan untuk menyelesaikan masalah ini: URL untuk membedah dan membangun URL, serta URLSearchParams untuk mengelola query string-nya dengan aman.

Keduanya bukan API khusus browser saja — spesifikasinya (WHATWG URL Standard) diikuti Node juga, sehingga berkas contoh di chapter ini bisa dijalankan langsung dengan node nama-berkas.js. Di halaman web, object yang sama tersedia sebagai global.

Membedah URL dengan new URL #

Aturannya: new URL(urlLengkap) mengurai string menjadi object dengan properti terpisah untuk setiap bagian. Dari satu string panjang, kita bisa membaca protokol, host, jalur, query string, dan fragment tanpa memotong string secara manual:

js urai-url.js
// urai-url.js — membedah URL menjadi bagian-bagiannya dengan new URL()

const tautan = new URL(
  "https://toko.example/katalog?kategori=buku&halaman=2#hasil"
);

console.log("protokol :", tautan.protocol);
console.log("host     :", tautan.host);
console.log("pathname :", tautan.pathname);
console.log("search   :", tautan.search);
console.log("hash     :", tautan.hash);
console.log("origin   :", tautan.origin);

// URL relatif membutuhkan URL dasar sebagai argumen kedua
const relatif = new URL("/promo/agustus", "https://toko.example");
console.log("relatif  :", relatif.href);

Output yang Dihasilkan:

text
protokol : https:
host     : toko.example
pathname : /katalog
search   : ?kategori=buku&halaman=2
hash     : #hasil
origin   : https://toko.example
relatif  : https://toko.example/promo/agustus

Mari kita telaah baris-baris pentingnya:

  1. Baris 3–5 (new URL(...)): constructor menerima URL absolut — lengkap dengan protokolnya. Bila string bukan URL valid, constructor melempar TypeError dengan pesan seperti Invalid URL, sehingga input dari pengguna bisa divalidasi lewat try-catch.
  2. Baris 7–12 (pembacaan properti): setiap bagian URL tersedia sebagai properti. search memuat tanda tanya beserta seluruh query string; hash memuat tanda pagar dan teks setelahnya; origin menggabungkan protokol dan host — berguna untuk membandingkan asal dua tautan.
  3. Baris 15 (new URL("/promo/agustus", dasar)): URL relatif tidak cukup sendirian karena hasilnya bergantung pada titik awal. Argumen kedua memberi URL dasar, dan constructor menggabungkan keduanya menjadi https://toko.example/promo/agustus.

Tabel berikut merangkum properti yang paling sering dibaca:

PropertiIsi pada contoh di atas
hrefURL utuh: https://toko.example/katalog?kategori=buku&halaman=2#hasil
protocolhttps: — catat tanda titik dua ikut menyertai
hosttoko.example — hostname plus port (bila ada)
pathname/katalog — jalur tanpa query dan hash
search?kategori=buku&halaman=2 — seluruh query string
hash#hasil — fragment di akhir URL
originhttps://toko.example — protokol plus host, tanpa jalur

Object URL juga bersifat dapat diubah (mutable): menulis ke satu properti memperbarui href sekaligus. tautan.pathname = "/katalog/anak" langsung mengubah URL utuhnya — tanpa membangun ulang string dari awal. Cara sebaliknya juga bisa: String(tautan) mengembalikan href sebagai string biasa, siap ditempel ke atribut href tautan atau dikirim ke fetch().

Membangun Query String dengan URLSearchParams #

Membangun tautan kebalikannya: kita punya data (kata kunci, urutan, tag) dan perlu menggabungkannya menjadi query string. Properti tautan.searchParams memberi object URLSearchParams yang terhubung langsung dengan URL pemiliknya — setiap perubahan pada params langsung terlihat di tautan.href:

// bangun-tautan.js — membangun dan mengubah query string secara aman

const tautan = new URL("https://toko.example/katalog");
const params = tautan.searchParams;

// --- 1. menambah parameter: set dan append ---
params.set("kata", "kamus mini"); // nilai berisi spasi: di-encode otomatis
params.set("urut", "harga");
params.append("tag", "baru");
params.append("tag", "promo"); // append menambah, bukan mengganti

console.log("tautan :", tautan.href);
console.log("kata   :", params.get("kata"));
console.log("tag    :", params.getAll("tag").join(", "));
console.log("halaman ada?", params.has("halaman"));

// --- 2. mengubah dan menghapus parameter ---
params.set("halaman", "2");
params.delete("urut");
console.log("akhir  :", tautan.href);

// --- 3. karakter khusus tetap aman tanpa pengodean manual ---
params.set("kata", "buku & novel");
console.log("search :", tautan.search);
console.log("terbaca:", params.get("kata"));

Output yang Dihasilkan:

text
tautan : https://toko.example/katalog?kata=kamus+mini&urut=harga&tag=baru&tag=promo
kata   : kamus mini
tag    : baru, promo
halaman ada? false
akhir  : https://toko.example/katalog?kata=kamus+mini&tag=baru&tag=promo&halaman=2
search : ?kata=buku+%26+novel&tag=baru&tag=promo&halaman=2
terbaca: buku & novel

Mari kita bedah method-methodnya:

  1. Baris 4 (tautan.searchParams): URLSearchParams diambil dari URL-nya. Keduanya saling terhubung — perubahan di satu sisi langsung tercermin di sisi lainnya.
  2. Baris 7 (params.set("kata", ...)): set(kunci, nilai) menambah parameter baru atau menimpa nilai yang sudah ada. Spasi pada “kamus mini” dikodekan menjadi + di dalam href tanpa kita campur tangan.
  3. Baris 9–10 (params.append(...)): append menambah nilai tanpa menghapus nilai sebelumnya, sehingga kunci tag muncul dua kali. get("tag") hanya mengembalikan yang pertama; getAll("tag") mengembalikan seluruhnya sebagai array.
  4. Baris 15 (params.has("halaman")): has memeriksa keberadaan kunci sebelum kita membacanya — hasilnya false karena parameter itu belum ditambahkan.
  5. Baris 18–19 (set dan delete): set("halaman", "2") menambah parameter di posisi akhir; delete("urut") menghapus kunci beserta seluruh nilainya dari URL.
  6. Baris 23–25 (karakter khusus): nilai “buku & novel” memuat & — karakter pemisah parameter. Di dalam search ia tampil sebagai %26, dan get("kata") mengembalikannya utuh kembali. Pengodean dan dekode berjalan dua arah secara otomatis.

Membaca Parameter dari Halaman Saat Ini #

Arah sebaliknya juga sering dibutuhkan: halaman katalog dibuka dengan URL yang sudah memuat parameter, lalu JavaScript membacanya untuk menyiapkan tampilan. Properti location.search berisi query string halaman aktif, dan URLSearchParams bisa menerima string itu langsung:

js Membaca parameter dari location.search
const params = new URLSearchParams(location.search);
const kata = params.get("kata") ?? "";
const halaman = Number(params.get("halaman") ?? "1");

console.log("kata kunci:", kata);
console.log("halaman   :", halaman);

Keluaran console browser:

text
kata kunci: kamus mini
halaman   : 2

Keluaran di atas mengasumsikan halaman dibuka pada URL https://toko.example/katalog?kata=kamus+mini&halaman=2; nilai tampil sudah terdekode kembali, tanpa tanda + maupun %26.

Properti hash layak mendapat satu catatan tersendiri. Bagian URL setelah # tidak pernah dikirim ke server — ia hanya dipakai browser untuk melompat ke jangkar (anchor) pada halaman, dan aplikasi satu halaman memakainya untuk rute seperti #/katalog/promo. Membaca dan mengubahnya memakai properti tautan.hash, dan perubahan dari tautan yang diklik pengunjung dilaporkan lewat event hashchange pada window — jalan pintas routing yang lebih tua daripada History API pada chapter berikutnya.

Sementara itu, origin adalah properti yang paling sering dipakai untuk keputusan keamanan: membandingkan tautanBaru.origin === location.origin memastikan tautan berada pada situs yang sama sebelum kode kita memperlakukannya secara khusus. Prinsip pemeriksaan ini kita kenali lagi di section Security sebagai bagian dari validasi URL.

Aturan pengodean URL sendiri (karakter mana yang harus dikodekan, perbedaan %20 dengan +) kita bedah lebih rinci di chapter URL Encoding pada section Data dan Serialization. Untuk pekerjaan sehari-hari — membedah tautan, membangun query string, membaca parameter halaman — pasangan URL dan URLSearchParams di chapter ini sudah menutup semua kebutuhannya.

Rangkuman pembagiannya begini: URL untuk URL utuh — validasi, pembacaan bagian, perubahan jalur; URLSearchParams untuk isi query string — tambah, baca, hapus parameter. Keduanya terhubung lewat properti searchParams, dan keduanya mengikuti spesifikasi yang sama di browser maupun Node, sehingga kode pemroses tautan kita bisa dipakai di kedua lingkungan tanpa penyesuaian.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

bangun-tautan.js

Unduh berkas
javascript
// bangun-tautan.js — membangun dan mengubah query string secara aman

const tautan = new URL("https://toko.example/katalog");
const params = tautan.searchParams;

// --- 1. menambah parameter: set dan append ---
params.set("kata", "kamus mini"); // nilai berisi spasi: di-encode otomatis
params.set("urut", "harga");
params.append("tag", "baru");
params.append("tag", "promo"); // append menambah, bukan mengganti

console.log("tautan :", tautan.href);
console.log("kata   :", params.get("kata"));
console.log("tag    :", params.getAll("tag").join(", "));
console.log("halaman ada?", params.has("halaman"));

// --- 2. mengubah dan menghapus parameter ---
params.set("halaman", "2");
params.delete("urut");
console.log("akhir  :", tautan.href);

// --- 3. karakter khusus tetap aman tanpa pengodean manual ---
params.set("kata", "buku & novel");
console.log("search :", tautan.search);
console.log("terbaca:", params.get("kata"));

urai-url.js

Unduh berkas
javascript
// urai-url.js — membedah URL menjadi bagian-bagiannya dengan new URL()

const tautan = new URL(
  "https://toko.example/katalog?kategori=buku&halaman=2#hasil"
);

console.log("protokol :", tautan.protocol);
console.log("host     :", tautan.host);
console.log("pathname :", tautan.pathname);
console.log("search   :", tautan.search);
console.log("hash     :", tautan.hash);
console.log("origin   :", tautan.origin);

// URL relatif membutuhkan URL dasar sebagai argumen kedua
const relatif = new URL("/promo/agustus", "https://toko.example");
console.log("relatif  :", relatif.href);