You can use a regular expression to match the different characters, and a callback function to determine what to replace it with. As it does all replacements in one run, there is no problem with one replacement containing another thing to replace:
s = s.replace(/[ab]/g, function(m){
switch (m) {
case 'a': return 'ab';
case 'b': return 'c';
}
return m;
});
Demo: http://jsfiddle.net/Guffa/pXSM5/
Edit:
To use regular expressions for matching each string, loop through them and find every match, then loop through the found matches and replace them. It's easiest to do the replacements starting with the last one in the string, that way you don't have to adjust the index of other matches when a replacement has a different length from the matched string:
var s = "a b";
var re = [{ regex: /a/g, replace: 'ab'}, { regex: /b/g, replace: 'c' }];
var pos = [];
for (var i = 0; i < re.length; i++) {
while ((r = re[i].regex.exec(s)) != null) {
pos.push({ index: r.index, match: r[0], replace: re[i].replace });
}
}
while (pos.length > 0) {
var last = 0;
for (var i = 0; i < pos.length; i++) {
if (pos[i].index > pos[last].index) last = i;
}
var p = pos[last];
s = s.substr(0, p.index) + p.replace + s.substr(p.index + p.match.length);
pos.splice(last, 1);
}
Demo: http://jsfiddle.net/Guffa/pXSM5/1/
Note: Make sure that the regular expressions doesn't match anything that can overlap.
"a b".split('').map( function( v ){ return v.replace('b', 'c').replace('a','ab'); }).join('')