What is the purpose of the 'y' sticky pattern modifier in JavaScript RegExps?

久未见 提交于 2021-02-04 17:54:10

问题


MDN introduced the 'y' sticky flag for JavaScript RegExp. Here is a documentation excerpt:

y

sticky; matches only from the index indicated by the lastIndex property of this regular expression in the target string (and does not attempt to match from any later indexes).

There's also an example:

var text = 'First line\nSecond line';
var regex = /(\S+) line\n?/y;

var match = regex.exec(text);
console.log(match[1]);        // prints 'First'
console.log(regex.lastIndex); // prints '11'

var match2 = regex.exec(text);
console.log(match2[1]);       // prints 'Second'
console.log(regex.lastIndex); // prints '22'

var match3 = regex.exec(text);
console.log(match3 === null); // prints 'true'

But there isn't actually any difference between the usage of the g global flag in this case:

var text = 'First line\nSecond line';
var regex = /(\S+) line\n?/g;

var match = regex.exec(text);
console.log(match[1]);        // prints 'First'
console.log(regex.lastIndex); // prints '11'

var match2 = regex.exec(text);
console.log(match2[1]);       // prints 'Second'
console.log(regex.lastIndex); // prints '22'

var match3 = regex.exec(text);
console.log(match3 === null); // prints 'true'

Same output. So I guess there might be something else regarding the 'y' flag and it seems that MDN's example isn't a real use-case for this modifier, as it seems to just work as a replacement for the 'g' global modifier here.

So, what could be a real use-case for this experimental 'y' sticky flag? What's its purpose in "matching only from the RegExp.lastIndex property" and what makes it differ from 'g' when used with RegExp.prototype.exec?

Thanks for the attention.


回答1:


The difference between y and g is described in Practical Modern JavaScript:

The sticky flag advances lastIndex like g but only if a match is found starting at lastIndex, there is no forward search. The sticky flag was added to improve the performance of writing lexical analyzers using JavaScript...

As for a real use case,

It could be used to require a regular expression match starting at position n where n is what lastIndex is set to. In the case of a non-multiline regular expression, a lastIndex value of 0 with the sticky flag would be in effect the same as starting the regular expression with ^ which requires the match to start at the beginning of the text searched.

And here is an example from that blog, where the lastIndex property is manipulated before the test method invocation, thus forcing different match results:

var searchStrings, stickyRegexp;

stickyRegexp = /foo/y;

searchStrings = [
    "foo",
    " foo",
    "  foo",
];
searchStrings.forEach(function(text, index) {
    stickyRegexp.lastIndex = 1;
    console.log("found a match at", index, ":", stickyRegexp.test(text));
});

Result:

"found a match at" 0 ":" false
"found a match at" 1 ":" true
"found a match at" 2 ":" false



回答2:


There is definitely a difference in behaviour as showed below:

var text = "abc def ghi jkl"
undefined
var regexy = /\S(\S)\S/y;
undefined
var regexg = /\S(\S)\S/g;
undefined
regexg.exec(text)
Array [ "abc", "b" ]
regexg.lastIndex
3
regexg.exec(text)
Array [ "def", "e" ]
regexg.lastIndex
7
regexg.exec(text)
Array [ "ghi", "h" ]
regexg.lastIndex
11
regexg.exec(text)
Array [ "jkl", "k" ]
regexg.lastIndex
15
regexg.exec(text)
null
regexg.lastIndex
0
regexy.exec(text)
Array [ "abc", "b" ]
regexy.lastIndex
3
regexy.exec(text)
null
regexy.lastIndex
0

..but I have yet to fully understand what is going on there.



来源:https://stackoverflow.com/questions/30291436/what-is-the-purpose-of-the-y-sticky-pattern-modifier-in-javascript-regexps

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!