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)
151: Groups, Flags, and Global Matching
I've seen a lot of developers hit a wall when they first start combining capturing groups with the global flag. The most common misconception is that string.match(/regex/g) will return an array of every match along with their corresponding captured groups. It feels intuitive—if you've defined a group to extract a specific piece of data, why wouldn't JavaScript give that to you for every occurrence it finds?
Let's look at why that's not how it works. Suppose we're parsing a log file to find all the "User: [Name]" entries.
const log = "User: Alice, User: Bob, User: Charlie";
const regex = /User: (\w+)/g;
const results = log.match(regex);
console.log(results);
// You'd expect: [["User: Alice", "Alice"], ["User: Bob", "Bob"]...]
// But you actually get: ["User: Alice", "User: Bob", "User: Charlie"]
Notice what happened? The capturing group (\w+) was completely ignored in the output. When you use the g flag with .match(), JavaScript prioritizes finding every single match and throws the group data away to keep the resulting array simple. It's a frustrating quirk, but once you know it, you can stop fighting the API.
Global matches actually hide your groups
If you actually need those captured groups for every match in a string, you have to change your approach. I usually reach for matchAll(). It returns an iterator instead of an array, which means you can loop through it and get the full match and the groups for every single hit.
const log = "User: Alice, User: Bob, User: Charlie";
const regex = /User: (\w+)/g;
const matches = log.matchAll(regex);
for (const match of matches) {
console.log(`Full match: ${match[0]}, Captured Name: ${match[1]}`);
}
// Full match: User: Alice, Captured Name: Alice
// Full match: User: Bob, Captured Name: Bob
// Full match: User: Charlie, Captured Name: Charlie
The key here is that matchAll() requires the g flag. If you forget it, JavaScript will throw a TypeError. It's the engine's way of saying, "If you want all matches, you have to explicitly tell me to look globally."
Isolating the gold with capturing groups
Capturing groups aren't just for matchAll(); they are your primary tool for data extraction. By wrapping a part of your regex in parentheses (), you're telling the engine, "I need to match this whole pattern, but I only care about this specific slice of it."
Sometimes, you need to group things for logic (like using a quantifier) but you don't actually want to "capture" that data into the results array. That's where non-capturing groups (?:...) come in. I use these all the time to keep my result arrays clean. If I'm matching (http|https)://, I only care about the protocol for the match to be valid, but I don't need "http" as a separate entry in my results.
Controlling the engine with flags
Flags are the modifiers that change how the entire regex engine behaves. You've seen g for global, but there are a few others you'll use daily:
i(Case-insensitive): Essential for user input./javascript/iwill match "JavaScript", "JAVASCRIPT", and "jAvAsCrIpT".m(Multiline): Changes how^and$work. Normally they match the start and end of the entire string. Withm, they match the start and end of each line.s(dotAll): By default, the dot.matches any character except newlines. Thesflag lets the dot match newlines too, which is a lifesaver when parsing HTML or multi-line text blocks.
I recommend being intentional with your flags. Don't just throw gi on everything; it can lead to "greedy" matches that pick up data you didn't intend to capture, making your bugs much harder to track down.
📋 Practical Task
Parsing Social Media Mentions and Hashtags
You are building a simple social media parser. You have a string containing a post, and you need to extract two things: all usernames (starting with @) and all hashtags (starting with #). However, you only want the actual text of the username or hashtag, not the symbol itself.
Requirements:
- Use
matchAll()to ensure you get the captured groups for every match. - Create a regex that captures the text following the @ or # symbol.
- Store the results in two separate arrays:
mentionsandhashtags. - Ensure the search is case-insensitive.
const post = "Loving the new features in #JavaScript! Shoutout to @DevMaster and @CodeQueen for the help. #CodingLife #webdev";
// Your code here:
// 1. Define your regexes with the appropriate flags
// 2. Use matchAll to extract the captured group (index 1 of the match)
// 3. Populate the arrays
const mentions = []; // Should become ["DevMaster", "CodeQueen"]
const hashtags = []; // Should become ["JavaScript", "CodingLife", "webdev"]
console.log("Mentions:", mentions);
console.log("Hashtags:", hashtags);
There are no comments for now.