string.replace with substitution by function

It may or may not be news to you that in Javascript you can do:

someString.replace(
/\w+/g,
function(match) {
return “blah”
}
);

Which in this case turns “the original string” into “blah blah blah”. Your function is passed the match, and you return whatever you want. That’s pretty handy, as you can run the match through transformations, or even use it to lookup or generate some entirely new value. You can also have side-effects from the match, which has interesting possibilities, not least of which is debugging:
1
function(match) { console.log("I matched %s", match); return match);

If you’re like me, you might even think you could do something like this:

someString.replace(
/<(\w+)[^>]*>)/g,
function(tag) {
var tagName = RegExp.$1;
return tagName.toLowerCase(); // or whatever…
}
);

.. but sadly you’d be wrong. At least as soon as you went to check in IE. It seems IE doesnt populate the properties from the match into the static RegExp object until after the whole replace is done. And your substitution function only gets passed the matched string, not the array of match + sub-matches you might be used to :(

Still, there’s plenty of mileage there. How about this:


function format(str, obj) {
var str = str.replace(/\${[^}]+}/g, function(mstr) {
var key = mstr.substring(2, mstr.length-1);
return (typeof obj[key] == “undefined”) ? “” : obj[key];
});
return str;
}

.. which takes a string like
1
"&lt;h1&gt;${firstname} ${lastname}&lt;/h1&gt;
, and an object like:
1
{ firstname: "Bob", lastname: "Smith" }
to produce
1
&lt;h1&gt;Bob Smith&lt;/h1&gt;