To another answer already explains how the code works, so I’ll focus on your other question:
There’s no simpler way to do that number-for-letter exchange?
There are other ways to do it, but whether they are simpler or not is a matter of opinion. Anyway, let’s go to them.
Option 1: Create a single regex instead of multiple
A feature of its code is that it creates several regular expressions, one for each key of the object passed (in this case, one regex for each digit). Maybe someone thinks it’s "simpler" to create a single regex (it might be a little "better" by creating fewer things and doing everything at once, for example, but again, it’s a matter of opinion).
We can join all keys of regex in a single expression and make a single replace
:
String.prototype.allReplace = function(obj) {
let r = new RegExp(Object.keys(obj).join('|'), 'g');
return this.replace(r, function(match) {
return obj[match];
});
};
console.log('T35t3 d3 35t4g1o'.allReplace({4: 'a', 3: 'e', 1: 'i', 5: 's'}));
In case, I get all the keys to obj
(which in this case are the digits 4, 3, 1 and 5) and together all in a single expression: 4|3|1|5
. This regex uses alternation (the character |
, which means or), which means she gets any of these digits.
Then I use a function in the second parameter of replace
, which in turn takes as a parameter the match (that is, the section that was found by regex). I know this excerpt can be any of the digits (4, 3, 1 or 5), so I return the corresponding value (the letters a
, e
, i
or s
, obtained from the own obj
), which will be the value used in substitution.
At the end, all digits are replaced by the respective letters.
Note: if all options have only one character (in this case, all are only one digit), regex could also be [4315]
. But I used toggle to make the code more "generic", so it can receive strings of various sizes. For example, if I want to trade abc
for xyz
:
String.prototype.allReplace = function(obj) {
let r = new RegExp(Object.keys(obj).join('|'), 'g');
return this.replace(r, function(match) {
return obj[match];
});
};
console.log('abc 123 abc'.allReplace({'abc': 'xyz'}));
Option 2: Do not use regex
It may be simpler to go through the string and replace its characters one by one, using the obj
to replace the desired characters, and keeping the others:
String.prototype.allReplace = function(obj) {
let s = '';
for (let i = 0; i < this.length; i++) {
let c = this.charAt(i);
if (obj.hasOwnProperty(c)) {
s += obj[c];
} else {
s += c;
}
}
return s;
};
console.log('T35t3 d3 35t4g1o'.allReplace({4: 'a', 3: 'e', 1: 'i', 5: 's'}));
For each character of the string, I use hasOwnProperty
to check whether obj
contains a key with that character. If so, I use the respective value in the substitution, and if not, I keep the same character as the original string.
The difference to the first option is that, as I am going through the characters one by one, it is no longer possible to exchange larger excerpts (like the previous example that changes abc
for xyz
).
Finally, these are some alternatives to your code. Whether it is simpler or not, it goes from the opinion of each...