2010-06-30 3 views
1

Я написал этот метод проверки, но у меня возникли проблемы с ним.Неожиданная проблема с поведением JavaScript

function validate_password(pwd) 
{ 
    var score = 0; 

    // Min length is 8 
    if (pwd.length<8) 
     return false; 

    // Is lower present? 
    if (/[a-z]/g.test(pwd)) 
    { 
     console.log('a-z test on "'+pwd+'":' + /[a-z]+/g.test(pwd)); 
     score++; 
    } 

    // Is upper present? 
    if (/[A-Z]/g.test(pwd)) 
    { 
     console.log('A-Z test on: "'+pwd+'":' + /[A-Z]+/g.test(pwd)); 
     score++; 
    } 

    // Is digit present? 
    if (/\d/g.test(pwd)) 
    { 
     console.log('digit test on: "'+pwd+'":' + /\d/g.test(pwd)); 
     score++; 
    } 

    // Is special char present? 
    if (/\W/g.test(pwd)) 
    { 
     console.log('spec char test on: "'+pwd+'":' + /\W/g.test(pwd)); 
     score++; 
    } 

    if (score>=3) 
     return true; 
    else 
     return false; 
} 

Это то, что написано в консоли:

>>> validate_password('aaasdfF#3s') 
a-z test on "aaasdfF#3s":true 
A-Z test on: "aaasdfF#3s":true 
digit test on: "aaasdfF#3s":true 
spec char test on: "aaasdfF#3s":true 
true 

>>> validate_password('aaasdfF#3s') 
a-z test on "aaasdfF#3s":true 
false 

На первой попытки, кажется, работает, как ожидалось, но когда я вызываю метод 2-й раз, он не работает, как ожидалось ,

Итак, мой вопрос, почему существуют различия между результатами первой попытки и второй попыткой?

Спасибо!)

+0

Я скопировал это на страницу и побежал его несколько раз подряд, и он побежал успешно для меня каждый раз. Возможно ли что-то еще? Или это одно и то же значение не передается каждый раз? – spinon

+0

Я загрузил страницу, а затем в Firebug дважды выполнил строку с той же строкой. Хммм ... странно. – 2010-06-30 19:04:00

+0

Вы уверены, что это код, который вы используете? Он не регистрирует окончательный счет в том или ином случае, когда вы вызываете эту функцию, и это не входит в какое-либо условие, поэтому всегда делайте это, прежде чем возвращать результат. – Guffa

ответ

1

См. Документацию MDC по адресу test.

Если вы хотите узнать, найден ли шаблон в строке, используйте метод тестирования (аналогично методу String.search); для получения дополнительной информации (но более медленного выполнения) используйте метод exec (аналогично методу String.match). Как и в случае с exec, тест , вызванный несколько раз в том же экземпляре регулярного выражения, будет проходить мимо предыдущего совпадения.

Решение удалить глобальный или g флаг из ваших регулярных выражений:

/[a-z]/ вместо /[a-z]/g, и так далее.

Рассмотрим этот simple example, чтобы понять, почему эта проблема существует:

var l = /[a-z]/g; 

// initial search starts at the beginning, matches "a" and returns true 
l.test("a"); // true 
// since the first character matched, lastIndex moves to the next index - 1 
l.lastIndex; // 1 

// this time we pass a different string to the regex, but unfortunatly it 
// starts searching from the lastIndex which is 1. There are no lower case 
// letters from this point onwards (only "---"), so return value is false. 
l.test("x---"); // false 
// Since this search failed, lastIndex wraps around to the beginning, so the 
// next search will work as expected 
l.lastIndex; // 0 

Для вашего данного входа "aaasdfF#3s", нижний корпус [a-z] тест удалось бы в 7 раз есть 7 строчных букв, но не 8-й раз , И снова преуспевают с 9-го по 15-й раз и так далее. Другие тесты будут терпеть неудачу каждый раз, так как есть только один из символов каждого типа: "F", "#" и "3", и он обертывается вокруг lastIndex до 0, когда тест выходит из строя.

Проблема, похоже, связана с тем, что состояние сохраняется в тех объектах RegExp между вызовами функций, что означает, что объект RegExp создается только один раз, а не каждый раз, когда вызывается функция. Этот маленький test подтверждает это:

function RegExpStatePersistenceTest() { 
    var regex = /[a-z]/g; 

    regex.counter = regex.counter || 0; 
    regex.counter++; 

    console.log("counter:" + regex.counter); 
} 

RegExpStatePersistenceTest(); // counter: 1 
RegExpStatePersistenceTest(); // counter: 2 
RegExpStatePersistenceTest(); // counter: 3 
RegExpStatePersistenceTest();​ // counter: 4 

Если новый объект был явно создан с использованием new RegExp(..), то при каждом вызове функции, свежий новый RegExp объект будет создан, и государство не будет сохраняться между вызовами.

см Также why-regexp-with-global-flag-in-javascript-give-wrong-results

+0

А, это объясняет это. Интересно, как заставить его начать сначала. Спасибо. – 2010-06-30 19:54:51

Смежные вопросы