As Pointy and Jared Farrish mentioned, .replace, like any other function, doesn't care about the expressions given as arguments, it only cares about the values they're evaluated to. Consider the following code:
var word = 'Loooooks';
console.log(word[0]); // logs 'L'
console.log(word[1]); // logs 'o'
console.log(word[2]); // also logs 'o'
console.log(word[3]); // also logs 'o'
console.log(word[1], word[3]) // logs 'o', 'o'
console.log(word[1] === word[3]); // logs true, different expressions but with equal values
In the example shown, word[1]
and word[3]
are expressions, and their values are 'o'
and 'o'
respectively :D, since expressions are evaluated to their values, doing:
word = word.replace(word[3], word[3].toUpperCase());
is effectively the same as doing:
word = 'Loooooks'.replace('o', 'o'.toUpperCase());
which will obviously replace the first 'o' it encounters in the string, producing the output 'LOooooks'
instead of 'LooOooks'
.
Therefore, in order to replace the right characters, you either split the word into an array, then iterate over each character, replacing the "odd" ones (they're tecnically even), and finally joining everything back together:
// spliting variable word into an array
var splitWord = word.split(''); // ['L', 'o', 'o', 'o', 'o', 'o', 'k', 's']
// iterating over each character, replacing the odd ones
for (let i = 0; i < splitWord.length; i++) {
if (i % 2 === 0) {
splitWord[i] = splitWord[i].toUpperCase();
}
}
// joining everything back together
word = splitWord.join('');
console.log(word); // LoOoOoKs
Jared Farrish version is basically a more compact way to do the same thing.
Or you can also use a Regular Expression to match every pair of characters and then upper casing the first character of each pair:
// The regex /..?/g matches every pair of characters while
// ignoring the absence of a last character in words with an odd
// number of characters.
word.replace(/..?/g, match => match[0].toUpperCase() + (match[1] || ''));
And if you're interested in really WeIrD CaSe a phrase or even some multi-line text with one single replace, instead of using /..?/g
you could use /[A-z][^]?/g
, to also match character pairs:
var text = 'this is\na\tfancy \n\r weird-cased\ntext!';
text = text.replace(/[A-z][^]?/g, match => match[0].toUpperCase() + (match[1] || ''));
console.log(text);