JS REGEX 09: Dynamic Text Replacement with replace() and Callback Functions in JavaScript
When most people think of string.replace()
, they picture something simple — changing "old"
to "new"
.
But in the hands of a creative coder, replace()
can do far more.
What if you want every match to be treated differently — for example, numbering each occurrence, modifying case, or looking up values dynamically from a data object? That’s when callback functions step into the scene.
Let’s break this down step by step.
🧠 What Is a Callback Function?
A callback function is simply a function passed as an argument to another function, so that the receiving function can call it when needed.
In the context of replace()
, JavaScript calls your function every time a match is found in the text.
Whatever value your callback returns will be used as the replacement for that specific match.
That means instead of a static replacement, you now have dynamic power — the ability to compute, transform, and decide the replacement on the fly.
⚙️ The Anatomy of replace()
with a Function
The method signature looks like this:
string.replace(regexp, function(match, group1, group2, ..., offset, fullString) { ... })
Let’s unpack this:
Parameter | Meaning |
---|---|
match |
The exact substring matched by the regex. |
group1, group2, ... |
Values captured by parentheses ( ) in your regex. |
offset |
The index position in the original string where the match begins. |
fullString |
The entire string being processed. |
When the regex uses the global flag g
, this callback is invoked for every single match.
🔹 Example 1: Replace Based on Position
Let’s start with a friendly scenario.
Goal: Replace the first "Some"
with "Start"
and the second one with "End"
.
const text = "Some string Some";
const result = text.replace(/Some/g, (match, offset, fullString) => {
if (offset === 0) {
return 'Start';
} else {
return 'End';
}
});
console.log(result); // "Start string End"
💬 What’s Happening:
- The regular expression
/Some/g
looks for every instance of"Some"
globally. - The callback runs twice, once for each match.
- For the first
"Some"
, theoffset
(its position) is0
, so we return"Start"
. - For the second
"Some"
, theoffset
is10
, so we return"End"
. - The string is reconstructed as
"Start string End"
.
This demonstrates how replace()
can make context-aware decisions!
🔹 Example 2: Building Templates Dynamically
Imagine you’re designing a small templating engine — the kind that fills in {placeholders}
with real values.
Let’s do that elegantly with a callback.
const template = "My name is {surname}, {name} {surname}";
const data = { name: "John", surname: "Doe" };
const result = template.replace(/{(.+?)}/g, (match, key) => {
return data[key];
});
console.log(result); // "My name is Doe, John Doe"
💬 Step-by-Step Breakdown:
-
The regex
/{(.+?)}/g
captures anything inside curly braces{ }
.- The parentheses
( )
create a capturing group, so the content (e.g.name
) is stored inkey
.
- The parentheses
-
The callback is executed for each match found:
- For
{surname}
→key = "surname"
- For
{name}
→key = "name"
- For
- Inside the callback, we return the corresponding value from our
data
object. replace()
builds the final string using those returned values.
💡 Notice that this approach is data-driven — if you change your object, the text automatically updates. That’s a taste of how templating engines like Handlebars or Mustache work under the hood.
🔹 Example 3: Transforming Matches Mathematically
Let’s go further — suppose we want to double every number found in a string.
const text = "3 apples and 5 oranges";
const result = text.replace(/\d+/g, (num) => {
return num * 2;
});
console.log(result); // "6 apples and 10 oranges"
💬 Explanation:
- The regex
/\d+/g
matches every sequence of digits. - Each match is passed as
num
to the callback. - The callback doubles it (
num * 2
). - The returned value replaces the original number.
This is dynamic text replacement at its best — your logic runs per match.
🔹 Example 4: Case Transformation
Want to capitalize every word?
const sentence = "hello world";
const result = sentence.replace(/\b\w/g, (char) => char.toUpperCase());
console.log(result); // "Hello World"
The regex \b\w
matches the first letter of every word (\b
= word boundary, \w
= word character).
Each letter is uppercased by the callback.
🧩 Why Use Callback Functions in replace()
?
Because they make your string transformations intelligent. Instead of blindly substituting text, you can:
- Compute new values (
num * 2
) - Reference external data (
data[key]
) - React to context (
offset
position) - Use conditions to replace selectively
In short: callback functions make replace()
dynamic, context-aware, and programmable.
🧠 Summary Table
Concept | Description |
---|---|
replace(regexp, callback) |
Invokes your function for each match |
match |
The actual substring matched |
offset |
Index where the match begins |
fullString |
The full string being processed |
Callback return value | The replacement text used for that match |
🧪 Practice Time — Let’s Code!
1️⃣ Replace every number in a string with its double.
➡ Example: "4 cats and 7 dogs"
→ "8 cats and 14 dogs"
2️⃣ Capitalize every first letter of a word.
➡ Example: "learn javascript"
→ "Learn Javascript"
3️⃣ Replace placeholders like {city}
in "Welcome to {city}"
➡ With data { city: "Lagos" }
→ "Welcome to Lagos"
4️⃣ Replace only even numbers in "1 2 3 4 5"
with "even"
.
➡ Result: "1 even 3 even 5"
5️⃣ Replace each vowel with its uppercase version.
➡ "hello world"
→ "hEllO wOrld"
🧩 Review Fill-Gap Questions
- A callback function is a function passed as an ____ to another function.
- In
replace()
, the callback runs once for every ____ found. - The first parameter of the callback is always the ____ text.
- The
offset
parameter represents the match’s ____ in the string. - Capturing groups inside the RegExp are returned as additional ____.
- The value returned by the callback becomes the actual ____ for that match.
- Using
/\d+/g
matches all sequences of ____. - To transform only the first letter of every word, use the boundary symbol ____.
- Callback-based replacements make
replace()
more ____ and flexible. - In the template example,
data[key]
retrieves the value corresponding to the ____ found inside{ }
.