By WebNest Studio Engineering Team
JavaScript Tutorial
The Document Object Model (DOM)
When a browser loads an HTML page, it doesn't just display the raw markup — it builds an in-memory tree structure called the Document Object Model (DOM). Every tag becomes a node in that tree, and JavaScript can read, modify, add, or remove those nodes at any time, which is what makes web pages interactive rather than static.
The DOM is not part of the JavaScript language itself; it's a browser-provided API. That's why DOM code only runs in a browser environment (not in Node.js by default) and why the global object you interact with is document, which represents the entire loaded page.
Why it matters
The DOM is the page as JavaScript sees it: a tree of objects that can be read and changed. Every interactive feature, from showing an error message to building a list from API data, comes down to selecting elements and modifying them. Frameworks do this for you, but they do it through the same DOM.
The DOM Tree
The DOM models a page as a hierarchy: document is the root, it contains the <html> element, which contains <head> and <body>, and so on down to individual text nodes. Each node has relationships you can traverse programmatically.
parentElement/parentNode— the containing element.children— a live collection of child elements (ignores text nodes).childNodes— all child nodes, including text and comment nodes.nextElementSibling/previousElementSibling— adjacent elements at the same level.
Selecting Elements
Modern JavaScript almost always uses document.querySelector() and document.querySelectorAll() because they accept any CSS selector, which is far more flexible than the older getElementById or getElementsByClassName. querySelector returns the first match (or null), while querySelectorAll returns a static NodeList of every match.
document.getElementById('id')— fastest, but only matches by id.document.querySelector('.card > h2')— first match for any CSS selector.document.querySelectorAll('li.active')— a NodeList you can loop withforEach.
Creating and Modifying Elements
You build new DOM content with document.createElement(), set its content or attributes, and attach it to the tree with methods like appendChild(), append(), or before()/after(). Existing elements are updated through properties like textContent (plain text, safe from HTML injection), innerHTML (parses a string as markup — use with caution on untrusted input), classList (add/remove/toggle CSS classes), and setAttribute()/getAttribute().
Examples
Selecting an element and updating its content and class
// HTML: <ul id="task-list"><li class="task">Buy milk</li></ul>
const list = document.querySelector('#task-list');
const firstItem = list.querySelector('.task');
firstItem.textContent = 'Buy milk and eggs';
firstItem.classList.add('done');
console.log(firstItem.outerHTML);
<li class="task done">Buy milk and eggs</li>
Creating a new element and appending it to the tree
const list = document.querySelector('#task-list');
const newItem = document.createElement('li');
newItem.textContent = 'Walk the dog';
newItem.classList.add('task');
list.appendChild(newItem);
console.log(list.children.length);
2
Common Mistakes
- Using
innerHTMLto insert user-provided text, which can introduce cross-site scripting (XSS) if the text contains HTML/script tags — usetextContentfor plain text instead. - Assuming
querySelectorAll()returns an array — it returns a NodeList, which supportsforEachbut not array methods likemap()orfilter()without converting it first (Array.from(nodeList)). - Running DOM-selecting code before the page has finished parsing, so
querySelectorreturnsnullfor elements that don't exist yet — placing scripts at the end of<body>or usingDOMContentLoadedavoids this. - Calling
getElementsByClassNameorgetElementsByTagNameand forgetting the result is a *live* HTMLCollection, which changes automatically as the DOM changes, unlike the static NodeList fromquerySelectorAll.
Exercise
Using the DOM, change the text of the heading to DOM practice, add the class highlight to the paragraph, and create a new paragraph containing Added by JavaScript and append it to main.
Expected result: the heading reads DOM practice, and a new paragraph appears at the bottom of the page.
// The page contains: <main> with an <h1>, a <p> and a <button>
// TODO: change the heading text
// TODO: add the class "highlight" to the existing paragraph
// TODO: create a paragraph with the text "Added by JavaScript" and append it to main
Show hints
document.querySelector("h1")returns the first matching element, andtextContentsets its text.- Create with
document.createElement("p"), then attach it withappend.
Show solution
// The page contains: <main> with an <h1>, a <p> and a <button>
document.querySelector("h1").textContent = "DOM practice";
document.querySelector("p").classList.add("highlight");
const paragraph = document.createElement("p");
paragraph.textContent = "Added by JavaScript";
document.querySelector("main").append(paragraph);
Quick quiz
1. What does document.querySelectorAll(".item") return?
- A. The first matching element
- B. An array
- C. A string of HTML
- D. A NodeList of every matching element
Show answer
D. A NodeList can be looped over with forEach, but it is not an array.
2. Why is textContent safer than innerHTML for showing text typed by a user?
- A. It treats the value as plain text, so any markup in it is not executed
- B. It is faster to type
- C. It supports more browsers
- D. innerHTML cannot show text
Show answer
A. Putting untrusted input into innerHTML can run an attacker's script: cross-site scripting.
3. What does document.querySelector("#menu") return when no element matches?
- A. undefined
- B. null
- C. It throws an error
- D. An empty NodeList
Show answer
B. Using the result without checking is the cause of "cannot read properties of null".
Interview questions
What is the DOM?
Show answer
The Document Object Model is the browser's representation of a page as a tree of objects, one for each element, attribute and piece of text. It is built from the HTML when the page loads. JavaScript uses the DOM API to find nodes, read and change their content, attributes and styles, add and remove nodes, and listen for events. Changing the DOM changes what is shown on screen.
What is the difference between innerHTML, textContent and innerText?
Show answer
innerHTML reads or sets the content as HTML, so tags in the string become elements; it must never be given untrusted input. textContent reads or sets the raw text of the node and all its descendants, treating everything as text. innerText returns only the text that is visibly rendered, taking CSS into account, which makes it slower. For plain text, textContent is the usual choice.
Key Points to Remember
- The DOM is a tree representation of the page that JavaScript can read and mutate at runtime.
querySelector/querySelectorAllaccept full CSS selectors and are the modern default for finding elements.- Use
textContentfor safe plain text andinnerHTMLonly for trusted markup. - New elements are built with
createElement()and attached with methods likeappendChild().
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Shows a live preview of your HTML, CSS and JavaScript. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering