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)
26: Labeled Statements and Loop Control
A few years ago, I was reviewing a PR for a teammate who was building a complex data grid for a financial dashboard. He had a nested loop—one for rows, one for cells—searching for a specific "error" value. Once he found that value, he needed to stop everything and trigger an alert. The problem was that a standard break only exits the innermost loop. To get out of the outer loop, he had created a boolean variable called foundError, set it to true, broke the inner loop, and then immediately checked that boolean in the outer loop to break again.
It worked, but it was clunky. It added three extra lines of noise and a variable that served no purpose other than acting as a signal. I showed him labeled statements, and the look of relief on his face was priceless. He realized he could just tell JavaScript exactly which loop to kill without the "flag" dance.
Breaking Out of the Deep End
In JavaScript, you can prefix a loop with an identifier followed by a colon. This is a "label." While you can label any statement, you'll almost exclusively use them with for, while, and do...while loops. When you call break labelName;, the engine doesn't just stop the current loop; it jumps completely out of the loop associated with that label.
Take a look at this scenario where we are searching through a 2D array of coordinates to find a specific target. Without a label, we'd be stuck in that "flag" logic I mentioned earlier.
const map = [
['empty', 'empty', 'empty'],
['empty', 'target', 'empty'],
['empty', 'empty', 'empty']
];
// We label the outer loop 'searchLoop'
searchLoop: for (let row = 0; row < map.length; row++) {
for (let col = 0; col < map[row].length; col++) {
if (map[row][col] === 'target') {
console.log(`Found it at ${row}, ${col}!`);
break searchLoop; // This kills the outer loop immediately
}
}
}
I'll be honest with you: you won't use labels in 95% of your code. Overusing them can make your logic jump around too much, which makes the code harder to trace. But when you're deep in nested loops, they are a surgical tool that keeps your code clean.
Skipping to the Next Outer Iteration
The continue statement usually just skips the rest of the current iteration of the loop it's in. But when combined with a label, continue labelName; does something different: it stops the current inner loop and jumps straight to the next iteration of the outer loop.
This is incredibly useful when you've determined that the current outer item is a "bust" and there's no point in checking the rest of its children. Imagine you're processing a list of users, and each user has a list of orders. If a user is marked as "inactive," you want to skip all their orders and move straight to the next user.
const users = [
{ name: 'Alice', active: true, orders: [101, 102] },
{ name: 'Bob', active: false, orders: [201, 202] },
{ name: 'Charlie', active: true, orders: [301] }
];
userProcess: for (let user of users) {
if (!user.active) {
continue userProcess; // Skip Bob's orders entirely and go to Charlie
}
for (let orderId of user.orders) {
console.log(`Processing order ${orderId} for ${user.name}`);
}
}
In this example, the inner loop for Bob never even starts. We just teleported back up to the userProcess loop for the next iteration. It's much more declarative than wrapping your inner loop in an if (user.active) block, especially if you have several such checks.
📋 Practical Task
The Dungeon Key Search Optimization
You are writing a script for a text-adventure game. The game map is a 2D array of strings. One of these strings is 'Golden Key'. You need to find the key and stop searching immediately once it's found.
Your Task:
- Create a 2D array called
dungeon(at least 3x3). Place'Golden Key'in one of the inner cells. - Implement a nested
forloop to iterate through thedungeon. - Use a labeled statement to break out of both loops the moment the
'Golden Key'is encountered. - Log the coordinates (row and column) of the key to the console.
- Log "Search complete" after the loops have finished to prove that the code didn't just crash, but successfully exited the loops.
There are no comments for now.