Как эта странная функция JavaScript для проверки подлинности?

Это функция:

var isPrime = function(x) {
    return (!(/^,?$|^(,,+?)\1+$/.test(Array(++x))));
};

Он работает для небольших чисел, но когда число велико, генерирует исключение с недопустимой длиной массива. Я не понимаю, что здесь происходит. Что делает тест RegEx? Почему этот код работает?

Ответ 1

Array(++x) сначала создает строку из x запятых.

Текущее выражение:

^,?$         // Match 1 , or none
|            // or ...
^(,,+?)\1+$  // A specific number of commas, elaboration below:

Число запятых равно как минимум 2 запятым, а затем повторяйте их до конца. Он пытается сделать следующее:

  • он сначала пытается совместить 2 запятые (,+? соответствует не менее 1 , лениво) и использовать это для соответствия всем кратным 2, кроме 2, потому что ссылка на \1 обязательна. Все кратные 2, потому что ^(,,)\1+$ соответствует четному числу ,.

    Sidenote: \1 - это обратная ссылка и будет соответствовать тому, что соответствовала первой группе захвата, в этом начальном случае (,,). Итак, на этом первом этапе \1 будет соответствовать 2 запятым.

    Если есть совпадение, это означает, что существует четное число запятых и что число не является простым.

  • если вышеуказанное не соответствует, оно соответствует 3 запятым и использует их для соответствия всем кратным 3, опять же, кроме 3. Все кратные 3, потому что ^(,,,)\1+$ соответствует числам , в кратных 3.

    Sidenote: на этот раз \1 будет соответствовать (,,,), так как теперь в группе захвата. Итак, на этом втором этапе \1 будет соответствовать 3 запятым.

    Если есть совпадение, это означает, что существует множество запятых, которые делятся на 3, и, следовательно, не простое число.

И так далее. Вы можете увидеть шаблон?


Итак, регулярное выражение будет проверять все числа от 2 до тех пор, пока (,,+?) не будет равным по длине, чем возвращает Array(++x). Конечно, для больших чисел вы можете получить разные виды ошибок:

  • Число, которое вы передаете функции слишком велико для регулярного выражения, вы получите "переполнение стека, поскольку регулярное выражение пытается сохранить слишком много вещей в памяти, поскольку оно пытается найти совпадение", как упомянула Флорис в комментариях (это происходит до следующей ошибки на node.js);

  • В массиве, образованном Array(++x), имеется слишком много элементов, которые JS не поддерживает.

Итак, если регулярное выражение совпадает, это не простое число. Именно поэтому у вас есть ! в начале, чтобы отрицать результат теста регулярного выражения.

Ответ 2

Array(++x).toString() - это строка из x запятых.

Это проверяет его:

  • ,?: ноль или одна запятая
  • (,,+?)\1+: повторение числа запятых не менее 2

Итак, он проверяет, что x есть либо

  • 0 или 1
  • или кратное числу, большему или равному 2

Это определение того, что не является простым.

Более подробное объяснение:

  • /^A|B$: A или B, от начала до конца
  • ,?: запятая, необязательная (так, 0 или 1
  • (,,+?): 1 или более запятых, но не жадных
  • \1+ первая группа повторяется один или несколько раз

Обратите внимание, что нет волшебства: это дорого, поскольку он будет просить двигатель проверить все возможные размеры (,,+?), пока он не найдет его.