RegExp.lastIndex

I just discovered something that I don’t quite understand when checking Reg.Exp.lastIndex.
I don’t understand why it would produce 0 rather than 9 when it is directly applied to it without using a variable.

const regex1 = /foo/g;
const str1 = 'table football, foosball';

regex1.test(str1);

console.log(regex1.lastIndex);        // output: 9
console.log(/foo/g.lastIndex);        // output: 0

Because you haven’t used any methods on that RegExp object. The point of lastIndex is to be useful if you are repeatedly applying a regex pattern to a string. So in the example, the test method is used on a string. The test runs, and the lastIndex for that particular instance of RegExp is incremented to 9. Then test could be ran again, now starting at that index, and so on. You haven’t done anything with the RegExp object on your last line, so the lastIndex is 0

Thanks for reply.

But please look at this below.

const regex1 = /foo/g;
const str1 = 'table football, foosball';

regex1.test(str1);
console.log(regex1.lastIndex);        // output: 9

regex1.test(str1);
console.log(/foo/g.lastIndex);        // output: 0

And if I switch to a variable for RegExp, it would produce 19 rather than 0:

const regex1 = /foo/g;
const str1 = 'table football, foosball';

regex1.test(str1);

console.log(regex1.lastIndex);        // output: 9

regex1.test(str1);
console.log(regex1.lastIndex);		  // output: 19

The 2nd snippet corresponds to what you mentioned but the 1st one does not when RegExp is not stored in a variable first… I don’t understand why.

That’s a new RegExp object, /foo/g, so lastIndex is 0, it can’t be anything else: you create it then immediately check the lastIndex

regex1 is one RegExp instance, /foo/g on the last line is a different one.

But if I just use /foo/g for all, it still does not produce the same results as with regex1:

const str1 = 'table football, foosball';

/foo/g.test(str1);
console.log(/foo/g.lastIndex);        // output: 0

/foo/g.test(str1);
console.log(/foo/g.lastIndex);		  // output: 0

Well if I rewrite this particular example, this is exactly the same as what you’ve just written one post up, but possibly clearer w/r/t what’s confusing you:

const str1 = 'table football, foosball';

const regex1 = /foo/g;
const regex2 = /foo/g;
const regex3 = /foo/g;
const regex4 = /foo/g;

regex1.test(str1);
console.log(regex2.lastIndex);

regex3.test(str1);
console.log(regex4.lastIndex)

regexes 2 and 4 have nothing to do with 1 and 2, they’re different objects, similarly 4 has nothing to do with 2

Thanks for the example. Yes, I understand your point.
But now I am stuck with why using /foo/g directly does not produce the same results… like the example I showed above.

Because every time you write /foo/g, that’s a new object, a new instance of RegExp. Every time you do it, you are doing new RegExp("foo", "g"): the /foo/g syntax is just sugar for that. Every time you construct a new RegExp object, it’s lastIndex property starts at 0. So lastIndex is only useful if you assign your newly created RegExp object to a variable then reuse it.

Ah I see! Now I got it.
Thank you for the explanation! :pray:

1 Like