9

数値の存在をテストするために (JavaScript で) RegExp オブジェクトを作成します。

var test = new RegExp( '[0-9]', 'g' );

こんな感じで使ってます

console.log( test.test( '0' ) ); // true
console.log( test.test( '1' ) ); // false - why?

これの出力はさらに紛らわしいです:

console.log( test.test( '1' ) ); // true
console.log( test.test( '0' ) ); // false - why?
console.log( test.test( '1' ) ); // true
console.log( test.test( '2' ) ); // false - why?
console.log( test.test( '2' ) ); // true - correct, but why is this one true?

g修飾子を削除すると、期待どおりに動作します。

私が信じているように、これはバグですか、それとも仕様の特定の部分ですか? g修飾子はこのように使用することになっていますか? (複数のタスクに同じ式を再利用しているため、修飾子がまったくありません)

4

3 に答える 3

7

ドキュメントごと:https ://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/test#Description

test同じグローバル正規表現インスタンスで複数回呼び出されると、前の一致を超えて進みます。

この動作を確認できます。

var test = new RegExp( '[0-9]', 'g' );
test.test('01'); //true
test.test('01'); //true
test.test('01'); //false

gさまざまな文字列に対して単一の一致を確認するだけの場合は、フラグを使用しても意味がありません。

于 2013-03-21T23:19:33.850 に答える
6

'g'フラグを削除します。'g'フラグを使用するlastIndexと、正規表現のプロパティが更新され(同じ文字列での連続検索の準備)、そのインデックス値から次の検索が開始されます(したがって、次の検索で誤った読み取りが行われます)。

ここで同様の質問と回答:Regex Javascript // gフラグが状態に影響するのはなぜですか?

于 2013-03-21T23:17:17.253 に答える
1

MDNによると、

同様にexec(または組み合わせて)、test同じグローバル正規表現インスタンスで複数回呼び出されると、前の一致を超えて進みます。

技術的には、ECMAScript 5.1仕様は言う

15.10.6.3 RegExp.prototype.test(文字列)

次の手順が実行されます。

  1. 文字列RegExp.prototype.execを引数として使用して、この RegExp オブジェクトに対して (15.10.6.2) アルゴリズムを評価した結果を match とします。
  2. matchが null でない場合は、 true;を返します。それ以外の場合は返品してfalseください。

15.10.6.2 RegExp.prototype.exec(文字列)

正規表現に対して文字列の正規表現一致を実行し、一致の結果を含む Array オブジェクトを返すかnull文字列が一致しなかった場合。

String ToString( string ) は、次のように正規表現パターンの出現を検索されます。

  1. Rをこの RegExp オブジェクトとします
  2. [...]
  3. [...]
  4. Rの [[Get]] 内部メソッドを引数 " " で呼び出した結果をlastIndexするlastIndex
  5. iをToInteger ( lastIndex ) の値とします。
  6. globalをRの [[Get]] 内部メソッドを引数 " " で呼び出した結果するglobal
  7. グローバルがの場合falsei = 0 とします。
  8. [...]
  9. [...]
  10. eをrのendIndexとします。
  11. グローバルがの場合true
    1. Rの [[Put]] 内部メソッドを引数 " lastIndex"、eおよび で呼び出しtrueます。
  12. [...]

したがって、この動作を回避するには、

  • グローバル フラグの使用を避けるg

    このように、ステップ 7 では、の代わりにiなります。0lastIndex

  • lastIndex使用後は手動でリセット

    プロパティの値はlastIndex、次の一致を開始する文字列位置を指定します。

    例えば、

    var test = /[0-9]/g;
    test.test('0');      // true
    test.lastIndex;      // 1
    test.lastIndex = 0;
    test.test('1');      // true
    
  • メソッドを使用matchまたは文字列化するsearch

    matchlastIndex0 にリセットし、search無視します。

    15.5.4.10 String.prototype.match (正規表現)

    [...] [If] globalがである場合、 rxtrueの [[Put]] 内部メソッドを引数 " " および 0 で呼び出します。 [...]lastIndex

    15.5.4.12文字列.prototype.search (正規表現)

    [...]正規表現パターンrxの出現を最初から値文字列で検索します。[...]検索を実行するとき、 regexpのプロパティと プロパティは無視されます。[...]lastIndexglobal

    例えば、

    var test = /[0-9]/g;
    test.test('0');        // true
    test.lastIndex;        // 1
    '0'.search(test) > -1; // true
    test.lastIndex;        // 1 (unaltered)
    !!'0'.match(test);     // true
    test.lastIndex;        // 0
    
于 2014-10-30T18:49:19.527 に答える