Child replacing a white floor tile

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:

  1. The regular expression /Some/g looks for every instance of "Some" globally.
  2. The callback runs twice, once for each match.
  3. For the first "Some", the offset (its position) is 0, so we return "Start".
  4. For the second "Some", the offset is 10, so we return "End".
  5. 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:

  1. The regex /{(.+?)}/g captures anything inside curly braces { }.

    • The parentheses ( ) create a capturing group, so the content (e.g. name) is stored in key.
  2. The callback is executed for each match found:

    • For {surname}key = "surname"
    • For {name}key = "name"
  3. Inside the callback, we return the corresponding value from our data object.
  4. 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

  1. A callback function is a function passed as an ____ to another function.
  2. In replace(), the callback runs once for every ____ found.
  3. The first parameter of the callback is always the ____ text.
  4. The offset parameter represents the match’s ____ in the string.
  5. Capturing groups inside the RegExp are returned as additional ____.
  6. The value returned by the callback becomes the actual ____ for that match.
  7. Using /\d+/g matches all sequences of ____.
  8. To transform only the first letter of every word, use the boundary symbol ____.
  9. Callback-based replacements make replace() more ____ and flexible.
  10. In the template example, data[key] retrieves the value corresponding to the ____ found inside { }.

<
Previous Post
🕒 Build a Digital Clock with JavaScript + Time-Based Greeting
>
Next Post
💻 Project: Building a Simple Login Page with JavaScript Credentials