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)
79: Manipulating Content and Attributes
I've spent a lot of time reviewing junior code, and there is one pattern that pops up almost every single time we get to DOM manipulation: the reflexive use of innerHTML for every single text change. It feels like the "Swiss Army Knife" of the DOM, and because it works, many developers assume it's the best tool for the job.
"innerHTML is the universal tool" vs "textContent is your safety net"
Let's look at why relying solely on innerHTML is a mistake. Imagine you're building a simple comment section. You have a variable userName that comes from a database or a user input field, and you want to put it inside a span.
const userName = "<img src='x' onerror='alert(\"Hacked!\")'>";
const display = document.querySelector('#user-display');
// The "common" way
display.innerHTML = userName;
If you use innerHTML here, the browser doesn't just see a string; it sees HTML instructions. In this case, it executes a malicious script. This is a classic Cross-Site Scripting (XSS) vulnerability. Even if you aren't worried about hackers, innerHTML is expensive. It forces the browser to tear down the existing DOM nodes inside that element and rebuild them from scratch, which kills performance if you're doing it inside a loop.
The fix is textContent. It tells the browser: "Treat this strictly as raw text. Do not parse it. Do not execute it."
// The professional way
display.textContent = userName;
// Result: The actual string "<img src..." is printed literally on the screen. No alert.
I only use innerHTML when I actually intend to inject HTML tags (like adding a tag inside a paragraph). For everything else, textContent is the gold standard.
"Attributes are only changed via setAttribute" vs "Direct property access is cleaner"
When you start manipulating attributes—like changing an image source or disabling a button—you'll see setAttribute('attribute', 'value') used everywhere. It's not wrong, but it's often unnecessary and verbose.
Most standard HTML attributes are mirrored as properties on the DOM object. For example, instead of this:
const profilePic = document.querySelector('#avatar');
profilePic.setAttribute('src', 'assets/new-photo.jpg');
profilePic.setAttribute('alt', 'New Profile Picture');
You can just do this:
const profilePic = document.querySelector('#avatar');
profilePic.src = 'assets/new-photo.jpg';
profilePic.alt = 'New Profile Picture';
It's shorter, reads more like standard JavaScript, and is generally faster. Now, you still need setAttribute for custom data attributes (like data-user-id), because those don't have direct properties on the element object. But for the common stuff—id, src, value, disabled—just hit the property directly.
📋 Practical Task
Build a Dynamic User Profile Toggle
You are building a profile card that needs to be updated dynamically based on a user's status. Create a small HTML snippet with an image (<img id="user-avatar">), a name (<span id="user-name">), and a "Status" button (<button id="status-btn">).
Write a JavaScript function that does the following when the button is clicked:
- Changes the
user-nameto "Jane Doe" usingtextContent. - Updates the
user-avatarsource to"https://i.pravatar.cc/150?u=jane"using direct property access. - Sets a custom data attribute
data-status="active"on the button usingsetAttribute. - Changes the button's own text to "Profile Updated" and sets its
disabledproperty totrue.
There are no comments for now.