Improve chained regex to replace vowels

I was presented with a JavaScript code challenge to create a function that will substitute all instances of a, e, i, o, u in a string with 0, 1, 2, 3, 4 (respectively). For example, “How about this string?” should become “H3w 0b34t th2s str2ng?”

Here’s how I solved the problem:

const hackerSpeak = (str) => {
return str.replace(/[aA]/g, 0).replace(/[eE]/g, 1).replace(/[iI]/g, 2).replace(/[oO]/g, 3).replace(/[uU]/g, 4)
}

I’m fairly new to RegEx, and find myself wondering if there’s a simpler way that would avoid chaining. Could I combine the RegEx into one expression that would know to replace aeiou with 01234 respectively?

An answer on this question led me to look into capture groups and back referencing, but it seems that’s for re-ordering/swapping the aeiou characters rather than replacing them with 01234. (Though I’m happy to be corrected.)

Answer

If you want to be able to vary the mapping from e.g. a -> 0 to something else then you can use this approach:

const str = "the cat sat on the mat and the cow in the undergrowth";
const mapping1 = { a: 0, e: 1, i: 2, o: 3, u: 4 }
const mapping2 = { a: "!", e: "foo", i: "bar", o: "fizz", u: "buzz" }
const hackerSpeak = (str, mapping) => {
  return str.replace(/(a)|(e)|(i)|(o)|(u)/gi, k => mapping[k]);
}
console.log(str);
console.log(hackerSpeak(str, mapping1));
console.log(hackerSpeak(str, mapping2));