Chapter sebelumnya berhenti tepat saat node-node selesai dirangkai menjadi DOM. Kini kita berhenti lebih lama pada hasil tersebut: apa itu DOM, bagaimana bentuknya, dan mengapa DOM tidak selalu sama dengan markup yang kita tulis. Pemahaman ini penting karena DevTools, JavaScript, dan sebagian besar perilaku browser bekerja pada DOM — bukan pada file HTML di server.
DOM adalah Representasi Objek Dokumen #
DOM (Document Object Model) adalah representasi berbasis objek dari sebuah dokumen di dalam memori browser. File HTML hanyalah teks; DOM adalah hasil pembacaan teks tersebut. Setiap element menjadi objek yang memiliki properti dan method, siap dibaca maupun diubah oleh program. Objek document menjadi titik masuknya — melalui objek inilah JavaScript menjangkau bagian mana pun dari halaman.
File di server tidak berubah ketika DOM berubah. Perubahan hanya terjadi pada salinan di memori browser, dan salinan itu dibangun ulang dari nol setiap kali halaman dimuat ulang.
Struktur Pohon: Element, Teks, dan Atribut #
DOM berbentuk pohon. Node paling atas adalah document, di bawahnya element html, lalu head dan body, dan seterusnya mengikuti nested markup. Tiga jenis node yang paling sering kita temui:
- Element node: satu objek untuk setiap element, misalnya
h1,p, danli. - Text node: isi teks di dalam element; spasi dan baris baru pada markup pun menjadi bagian teks.
- Atribut: nilai seperti
hrefdanclasstersimpan pada objek element yang memilikinya, bukan sebagai node anak dalam pohon.
File berikut adalah halaman kecil yang akan kita bedah wujud DOM-nya. Simpan sebagai contoh-dom-overview.html:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Daftar Belanja Budi</title>
</head>
<body>
<h1>Daftar Belanja</h1>
<p>Budi menulis daftar sebelum pergi ke pasar.</p>
<ul>
<li>Beras 5 kg</li>
<li>Gula 1 kg</li>
</ul>
</body>
</html>Setelah diparsing, wujud pohon DOM-nya kira-kira sebagai berikut:
document
└── html
├── head
│ ├── meta (charset)
│ ├── meta (viewport)
│ └── title → teks "Daftar Belanja Budi"
└── body
├── h1 → teks "Daftar Belanja"
├── p → teks "Budi menulis daftar sebelum pergi ke pasar."
└── ul
├── li → teks "Beras 5 kg"
└── li → teks "Gula 1 kg"Berikut peran setiap bagian file dalam pohon di atas:
- Baris 4 (
<meta charset="utf-8">): element node sederhana tanpa isi; atributcharsettersimpan pada objek element-nya. - Baris 6 (
<title>): element node dengan satu text node sebagai anak; isi teks inilah yang tampil pada tab browser. - Baris 9-10 (
<h1>dan<p>): dua element node sejajar di bawahbody, masing-masing membawa satu text node. - Baris 11-14 (
<ul>dan dua<li>): contoh nested; kedua elementlimenjadi anak elementul, dan parser memastikan penempatannya tepat. - Baris 15-16 (tag penutup): parser menutup node yang tersisa, lalu pohon dianggap selesai dan siap diperlakukan CSS.
DOM Bersifat Live #
DOM disebut live: perubahan lewat JavaScript langsung terlihat pada halaman tanpa reload. Buka contoh di atas, lalu jalankan baris berikut pada console DevTools:
document.querySelector("h1").textContent = "Daftar Belanja Dewi";Heading di layar berganti nama seketika, dan panel Elements ikut menampilkan teks baru. Yang tidak berubah adalah file contoh-dom-overview.html di server — hanya salinan memori sajalah yang berubah. Sifat live inilah yang memungkinkan JavaScript memperbarui sebagian halaman tanpa reload.
Ketika DOM Berbeda dari Markup #
Parser HTML tidak berhenti ketika menemui markup yang salah tulis; parser memperbaikinya mengikuti aturan error recovery yang dibakukan pada spesifikasi. Akibatnya, DOM bisa berbeda dari yang tampak kita tulis. Contoh pertama, tag penutup p boleh ditinggalkan ketika paragraf lain menyusul:
<p>Butir pertama catatan Budi
<p>Butir kedua catatan BudiMarkup tersebut tampak seperti satu paragraf berisi paragraf lain. Parser membacanya secara berbeda: ketika token start tag p kedua tiba, parser menutup paragraf pertama secara implisit. DOM yang terbentuk berisi dua element p yang bersaudara — sejajar di bawah body, bukan satu node di dalam node lain.
Contoh kedua, tag penutup yang salah pasang:
<p>Teks awal <b>tebal</i> berlanjut di sini</p>Penulisnya bermaksud menghentikan penekanan pada </i>, padahal yang dibuka adalah b. Parser mengabaikan tag penutup yang tidak berpasangan, sehingga teks “berlanjut di sini” ikut berada di dalam element b. Panel Elements akan menampilkan b yang menampung teks setelahnya — bukan hanya kata “tebal”.
Satu konsekuensi terakhir sering mengejutkan pemula: panel Elements pada DevTools menampilkan DOM live, bukan isi file. Bila parser memperbaiki markup atau JavaScript mengubah halaman, panel Elements menunjukkan hasil akhirnya. Chapter berikutnya membandingkan panel ini dengan view-source, pintu lain menuju halaman yang sama.
Referensi resmi untuk pendalaman:
- MDN Web Docs — Document Object Model (DOM)
- MDN Web Docs — Introduction to the DOM
- WHATWG — DOM Living Standard
- WHATWG — HTML Living Standard: Writing HTML documents
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
contoh-dom-overview.html
Unduh berkas<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Daftar Belanja Budi</title>
</head>
<body>
<h1>Daftar Belanja</h1>
<p>Budi menulis daftar sebelum pergi ke pasar.</p>
<ul>
<li>Beras 5 kg</li>
<li>Gula 1 kg</li>
</ul>
</body>
</html>