Methods in JavaScript

Earlier we covered the method replace() from the String prototype with its special replacement patterns. RegExp method test() can be used to determine if and String method search() can be used to determine where a certain pattern can be found in a string.


let beginWord = "Dear";
let str = 'Dear all,';

let regex = new RegExp(`^${beginWord}`);
// The RegExp argument is a template string literal with a variable.
// The special character ^ matches the beginning of input.
//console.log(regex); // logs: /^Dear/

if (regex.test(str)) {
   console.log(`'${str}' starts with the word '${beginWord}'`); // logs: "'Dear all,' starts with the word 'Dear'"
} else {
   console.log(`'${str}' does NOT start with the word '${beginWord}'`);
}

BTW, this example is just to show the working of method test(). It may be better to use String.prototype.startsWith() to determine whether a string begins with a specified string. P.S. Also String.prototype.endsWith() exists.


const text = "The sharecropper's old nag";
const regex = /'/g;
const regexDot = /[.]/g; // equivalent to /\./g
console.log(text.search(regex));   // logs: 16 // which is the index of the first character "'"
console.log(text.search(regexDot)); // logs: -1 // cannot find a dot '.'

Methods exec(), match() and matchAll()

RegExp method exec() and String methods match() and matchAll() retrieve an array of matching sequences from a string with a pattern defined by a regular expression.

exec()
If you only want to obtain the first match, including capturing groups.
match()
If you want to obtain all results (set the g flag) matching the regular expression, but not capturing groups.
matchAll()
If you want to obtain all results matching the regular expression, including capturing groups. matchAll() will throw an exception if the global flag (g) is missing.

let text = "When he shall die, Take him and cut him out in little stars.";
const regex = /shall\s(die).+?(out)/i;
let resultArray = regex.exec(text);
console.log(resultArray); // logs: [ "shall die, Take him and cut him out", "die", "out" ]
console.log(resultArray[0]); // logs: "shall die, Take him and cut him out"
console.log(resultArray[1]); // logs: "die" // first capturing group
console.log(resultArray[2]); // logs: "out" // second capturing group

let text = "When he shall die, Take him and cut him out in little stars, And he will make the face of heaven so fine. That all the world will be in love with night. And pay no worship to the garish sun.";
const regExpVowels = /[aeiouy]/g;
let arrayOfVowels = text.match(regExpVowels);
console.log(arrayOfVowels); // logs: [ "e", "e", "a", "i", "e", "a", "e", "i", "a", "u", … ]
console.log(`Number of vowels in the text: ${arrayOfVowels.length}.`); // logs: "Number of vowels in the text: 52."

In the next sample a for...of loop is used to iterate over the matching results stored in an array of arrays.


const regex = /foot([a-z]*)/g; // regular expression with capturing group
const str = 'footmark footstep football';
const matches = str.matchAll(regex);
for (let match of matches) {
   console.log(`'${match[0]}' found at index ${match.index}, and capture '${match[1]}'.`);
   // console.log(`${match[0].substring(4)}, ${match[1]}`);
}

/* logs:
"'footmark' found at index 0, and capture 'mark'."
"'footstep' found at index 9, and capture 'step'."
"'football' found at index 18, and capture 'ball'."
*/

With matchAll() (and with exec()) you can specify at what index in the string the search should start. The default start index is 0. You can specify the start index by setting the RegExp property lastIndex. The engine starts searching at index lastIndex and then continues to the end. If a match is found, the lastIndex property is automatically updated to the index where the regex failed. Because of the global search (g flag) a next search starts, and it starts at this updated lastIndex. By explicitly changing the initial default lastIndex from 0 to an integer greater than 0, before calling matchAll(), you can alter the start index.


const regex = /foot([a-z]*)/g;
const str = 'footmark footstep football';
regex.lastIndex = 8; // search begins at index 8: the space after "footmark".
const matches = str.matchAll(regex);
for (let match of matches) {
   console.log(`'${match[0]}' found at index ${match.index}, and capture '${match[1]}'.`);
}

/* logs:
"'footstep' found at index 9, and capture 'step'."
"'football' found at index 18, and capture 'ball'."
*/

In the above example the search starts at index 8. A match fails, so the engine returns to the beginning of the regex and to the next character of the string. There it finds a match until the regex fails at index 17. lastIndex is updated and the next search starts at this updated lastIndex.

If you want to test for a match only from the initial lastIndex and not attempting to match from any updated indexes, you can use the sticky flag y. In the example below the sticky flag is set. It finds a match at index 0 (which is the default start lastIndex) but then it fails to find a match at index 8 and 17.


const regex = /foot([a-z]*)/yg;
const str = 'footmark footstep football';
const matches = str.matchAll(regex);
for (let match of matches) {
   console.log(`'${match[0]}' found at index ${match.index}, and capture '${match[1]}'.`);
}

/* logs:
"'footmark' found at index 0, and capture 'mark'."
*/

Now consider the next example:


const regex = /foot([a-z]{4})/yg;
const str = 'footmarkfootstepfootball';
const matches = str.matchAll(regex);
for (let match of matches) {
   console.log(`'${match[0]}' found at index ${match.index}, and capture '${match[1]}'.`);
}

/* logs:
"'footmark' found at index 0, and capture 'mark'."
"'footstep' found at index 8, and capture 'step'."
"'football' found at index 16, and capture 'ball'."
*/