>// → 2
>console.log(" ".search(/\S/));
>// → -1
К сожалению, никак нельзя задать, чтобы метод искал совпадение, начиная с конкретного смещения (как это можно сделать с >indexOf
). Это было бы полезно.
Метод exec тоже не даёт удобного способа начать поиск с заданной позиции в строке. Но неудобный способ даёт.
У объекта регулярок есть свойства. Одно из них – >source
, содержащее строку. Ещё одно – >lastIndex
, контролирующее, в некоторых условиях, где начнётся следующий поиск вхождений.
Эти условия включают необходимость присутствия глобальной опции >g
, и то, что поиск должен идти с применением метода >exec
. Более разумным решением было бы просто допустить дополнительный аргумент для передачи в >exec
, но разумность – не основополагающая черта в интерфейсе регулярок JavaScript.
>var pattern = /y/g;
>pattern.lastIndex = 3;
>var match = pattern.exec("xyzzy");
>console.log(match.index);
>// → 4
>console.log(pattern.lastIndex);
>// → 5
Если поиск был успешным, вызов >exec
обновляет свойство >lastIndex
, чтобы оно указывало на позицию после найденного вхождения. Если успеха не было, >lastIndex
устанавливается в ноль – как и >lastIndex
у только что созданного объекта.
При использовании глобальной переменной-регулярки и нескольких вызовов >exec
эти автоматические обновления >lastIndex
могут привести к проблемам. Ваша регулярка может начать поиск с позиции, оставшейся с предыдущего вызова.
>var digit = /\d/g;
>console.log(digit.exec("here it is: 1"));
>// → ["1"]
>console.log(digit.exec("and now: 1"));
>// → null
Ещё один интересный эффект опции >g
в том, что она меняет работу метода >match
. Когда он вызывается с этой опцией, вместо возврата массива, похожего на результат работы >exec
, он находит все вхождения шаблона в строке и возвращает массив из найденных подстрок.
>console.log("Банан".match(/ан/g));
>// → ["ан", "ан"]
Так что поосторожнее с глобальными переменными-регулярками. В случаях, когда они необходимы – вызовы >replace
или места, где вы специально используете >lastIndex
– пожалуй и все случаи, в которых их следует применять.
Типичная задача – пройти по всем вхождениям шаблона в строку так, чтобы иметь доступ к объекту >match
в теле цикла, используя >lastIndex
и >exec
.
>var input = "Строчка с 3 числами в ней... 42 и 88.";
>var number = /\b(\d+)\b/g;
>var match;
>while (match = number.exec(input))
> console.log("Нашёл ", match[1], " на ", match.index);
>// → Нашёл 3 на 10
>// Нашёл 42 на 29
>// Нашёл 88 на 34
Используется тот факт, что значением присвоения является присваиваемое значение. Используя конструкцию