1. ホーム
  2. javascript

[解決済み] Javascriptの正規表現は、true, then false, then true...などを返す [重複].

2022-06-11 11:05:06

質問

あるフォームに書いているバリデーションに奇妙な問題があります。それは、入力の隣にある「ユーザー名を確認する」ボタンです。入力のデフォルト値はユーザー名で、例えば「betamax」です。Check Username'を押すと、正規表現を通過し、ユーザー名がサーバーに送信されます。サーバーは期待通りの動作をし、'2'を返して、自分自身のユーザー名を送信していることをJavaScriptに伝えます。

次に、ボタンを再度クリックすると、正規表現が失敗します。正規表現が失敗したため、サーバーには明らかに何も送信されません。もう一度ボタンを押すと、正規表現が成功し、ユーザー名がサーバーに送信されます。

何がこのようにさせるのか、文字通り理解できません! 私には意味がわかりません!

編集: Firefox と Chrome (mac) でこの問題をテストしました。

これは私のコードです。

$j("#username-search").click(checkUserName);

function checkUserName() {
    var userName = $j("#username").val();


    var invalidUserMsg = 'Invalid username (a-zA-Z0-9 _ - and not - or _ at beginning or end of string)';
    var filter = /^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi;
    if (filter.test(userName)) {
        console.log("Pass")
        $j.post(
        "/account/profile/username_check/", 
        { q: userName }, 
        function(data){
            if(data == 0) {
                $j("#username-search-results").html("Error searching for username. Try again?");
            }
            else if(data == 5) {
                $j("#username-search-results").html(invalidUserMsg);
            }
            else if(data == 4) {
                $j("#username-search-results").html("Username too short or too long.");
            }
            else if(data == 2) {
                $j("#username-search-results").html("This is already your username.");
            }
            else if(data == 3) {
                $j("#username-search-results").html("This username is taken.");
            }
            else if(data == 1){
                $j("#username-search-results").html("This username is available!");
            }
        });
    } else {
        console.log("fail")
        $j("#username-search-results").html(invalidUserMsg);
    }

    return false;

}

HTMLのことです。

<input name="username" id="username" value="{{ user.username }}" />
<input type="button" value="Is it taken?" id="username-search">
<span id="username-search-results"></span>

どのように解決するのですか?

/^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi;

を使っているのは g (グローバル) RegExp . JavaScript では、グローバルな正規表現には状態があります。 exec , test など) を初めて呼び出すと、与えられた文字列の中で最初にマッチするものが得られます。もう一度呼び出すと、次のマッチが得られ、マッチが得られなくなり、次の文字列の先頭にリセットされるまで、それを繰り返す。また、次のように書くこともできます。 regex.lastIndex= 0 と書いて、この状態をリセットすることもできます。

(もちろん、これは絶対にひどい設計で、混乱させ、奇妙なエラーを引き起こすことが保証されています。JavaScriptへようこそ!)

を省略することができます。 g を省略できます。 RegExp というように、1つのマッチしかテストしていません。

また、私はあなたが [^-_] は必要ないと思います。そうすると 任意の 文字が使えるようになります。 *plop! は有効です。おそらく lookahead/lookbehind アサーションを考えているのでしょうが、これらは JavaScript では利用できません。(まあ、lookaheadはあるはずなのですが、IEでは壊れています。) 代わりに提案します。

/^[a-z0-9][a-z0-9_-]{2,18}[a-z0-9]$/i