JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
78: Selecting and Traversing DOM Elements
I remember a project a few years back where a teammate was struggling with a massive data table. He was trying to implement a "Delete" button for each row, and his approach was to manually assign a unique ID to every single <tr> element—row-1, row-2, and so on. When the table grew to 500 rows, his code became a nightmare of string concatenation and brittle logic. I sat him down and showed him that he didn't need to know the ID of the row; he just needed to know where the button lived in relation to the row. That's the power of DOM traversal.
Grabbing the Right Element with CSS Selectors
Before you can move around the DOM, you have to get your foot in the door. While you've probably seen getElementById, in my day-to-day work, I almost exclusively use querySelector and querySelectorAll. Why? Because they use CSS selectors. If you already know how to style an element in CSS, you already know how to find it in JavaScript.
If you need one specific element, document.querySelector('.menu-item.active') is your best friend. If you need a collection, querySelectorAll returns a NodeList. Now, a quick word of caution: a NodeList isn't a true Array. You can use forEach on it, but if you want to use map or filter, you'll need to spread it into an array first: [...document.querySelectorAll('.item')]. I've seen countless bugs where developers tried to call .map() on a NodeList and wondered why their app crashed.
// The "Old Way"
const header = document.getElementById('main-header');
// The "Flexible Way"
const activeLinks = document.querySelectorAll('nav a.active');
const firstSidebarItem = document.querySelector('.sidebar .item:first-child');
Navigating the Family Tree: Parents and Siblings
Selecting an element is great, but the real magic happens when you start traversing. Think of the DOM as a family tree. Sometimes you have a reference to a button, but you need to change the background color of the entire container that holds that button. This is where parentElement and closest() come in.
parentElement takes you up one level. But what if your button is buried inside three nested <div> tags? That's where closest() is a lifesaver. It climbs up the DOM tree until it finds the first element that matches the selector you provide. It's far more robust than chaining .parentElement.parentElement.parentElement, which will break the second you add a wrapper div for styling.
Moving down or sideways is just as easy. children gives you the direct descendants, and nextElementSibling or previousElementSibling lets you jump to the neighbor. I often use these when building custom accordions or tabs where clicking one item needs to close the one immediately following it.
// Assume we are inside a click event handler for a button
const btn = event.target;
// Jump up to the nearest row, regardless of how deep the button is
const row = btn.closest('.table-row');
row.classList.add('highlighted');
// Find the specific status span inside that same row
const statusCell = row.querySelector('.status-label');
statusCell.textContent = 'Processing...';
// Move to the next row to maybe trigger a visual cue
const nextRow = row.nextElementSibling;
if (nextRow) {
nextRow.style.opacity = '0.5';
}
📋 Practical Task
Building a Dynamic Shopping Cart Item Manager
Create a simple HTML structure representing a shopping cart. Each item should be a <div> with a class of cart-item, containing a product name (in a <span>), a quantity input, and a "Remove" button.
Write a JavaScript script that does the following:
- Adds a single event listener to the parent container (using event delegation) or individual listeners to the "Remove" buttons.
- When a "Remove" button is clicked, use
.closest('.cart-item')to find the specific item container. - Once the container is found, use
.querySelector()to find the product name span andconsole.loga message saying: "Removing [Product Name] from cart." - Finally, use the
.remove()method to delete that specific item from the DOM.
There are no comments for now.