次の正規表現コードがあるとします。
var str = "{$ for ( var i = 0, len = O.length; i < len; i++ ) { $}";
var reg = /\{\$(.*?)\$\}/g;
console.log(reg.test(str));
console.log(reg.test(str));
console.log(reg.test(str));
結果が True と False の交互になるのはなぜですか?
次の正規表現コードがあるとします。
var str = "{$ for ( var i = 0, len = O.length; i < len; i++ ) { $}";
var reg = /\{\$(.*?)\$\}/g;
console.log(reg.test(str));
console.log(reg.test(str));
console.log(reg.test(str));
結果が True と False の交互になるのはなぜですか?
ドキュメントごと:
文字列にパターンが含まれているかどうかを知りたい場合は、test メソッドを使用します (String.search メソッドと同様)。詳細については (ただし、実行速度は遅くなります)、exec メソッドを使用します (String.match メソッドに似ています)。exec (またはそれと組み合わせて) と同様に、同じグローバル正規表現インスタンスに対して複数回呼び出されたテストは、前の一致を超えて進みます。
何が起こっているかを説明するために、何が起こっているのかを使用exec
して見ることができます。パスの順序:
null
(偽)null
ます。証明のために、次を実行します。
var str = '{$ for ( var i = 0, len = O.length; i < len; i++ ) { $}';
var reg = /\{\$(.*?)\$\}/g;
for (var i = 0; i < 3; i++){
var result = reg.exec(str);
console.log(result);
console.log(!!result);
}
JavaScriptは、最後に一致したインデックスなどのフィールドを含め、状態を内部的にRegExp
維持します。そのため、例のように正規表現を再利用すると、興味深い動作が見られます。
この/g
フラグによりtrue
、指定された文字列 (この例ではたまたま 1 つしかありません) に対する連続する一致ごとに 1回返さfalse
れ、その後、1 回返されてから最初からやり直されます。各呼び出しの間に、前述のlastIndex
プロパティが適宜更新されます。
次の点を考慮してください。
var str = "12";
var regex = /\d/g;
console.log(regex.test(str)); // true
console.log(regex.test(str)); // true
console.log(regex.test(str)); // false
対:
console.log(/\d/g.test(str)); // true
console.log(/\d/g.test(str)); // true
console.log(/\d/g.test(str)); // true
console.log(/\d/g.test(str)); // true
// ...and so on, since you're instantiating a new RegExp each time
面白い発見!グローバル修飾子 '/g' と関係があると思います。グローバル修飾子を削除すると、期待どおりに機能するようです。私は正規表現の専門家ではありません。.test() は、2 回一致するべきではありませんが、$ シンボルを反復処理できると推測することしかできませんでした。