La mejor manera de verificar alfanumérico en Javascript

107

¿Cuál es la mejor manera de realizar una verificación alfanumérica en un INPUTcampo en JSP? He adjuntado mi código actual

<script type="text/javascript">
  function validateCode(){
      var TCode = document.getElementById('TCode').value;
      for(var i=0; i<TCode.length; i++)
      {
        var char1 = TCode.charAt(i);
        var cc = char1.charCodeAt(0);

        if((cc>47 && cc<58) || (cc>64 && cc<91) || (cc>96 && cc<123))
        {

        }
         else {
         alert('Input is not alphanumeric');
         return false;
         }
      }
     return true;     
   }

t0mcat
fuente
2
Depende de cómo se defina "mejor". La mayoría de las respuestas a continuación sugieren regex, que funciona mucho más lento que su código original . He limpiado un poco tu código , que en realidad funciona muy bien.
Michael Martin-Smucker

Respuestas:

100

Puedes usar esta expresión regular /^[a-z0-9]+$/i

Mahesh Velaga
fuente
4
por supuesto, esto supone que la cadena vacía ( "") no debe coincidir.
zzzzBov
15
ñno entra en el patrón, sin embargo, el carácter UTF-8 es totalmente válido.
Oybek
8
/ ^ [a-z0-9] + $ / i.test (TCode)
Alex V
3
Probar una expresión regular parece ser mucho más lento (66% en Chrome 36) que charCodeAt(). Vea jsPerf y mi respuesta a continuación .
Michael Martin-Smucker
5
Esta expresión regular no funciona con letras de caracteres especiales que se utilizan en algunos idiomas, como "ą", "ź", "ć", etc.
Rafał Swacha
79

La inclinación de uso original del autor de la pregunta str.charCodeAt(i)parece ser más rápida que la alternativa de expresión regular. En mi prueba en jsPerf, la opción RegExp funciona un 66% más lento en Chrome 36 (y un poco más lento en Firefox 31).

Aquí hay una versión limpia del código de validación original que recibe una cadena y devuelve trueo false:

function isAlphaNumeric(str) {
  var code, i, len;

  for (i = 0, len = str.length; i < len; i++) {
    code = str.charCodeAt(i);
    if (!(code > 47 && code < 58) && // numeric (0-9)
        !(code > 64 && code < 91) && // upper alpha (A-Z)
        !(code > 96 && code < 123)) { // lower alpha (a-z)
      return false;
    }
  }
  return true;
};

Por supuesto, puede haber otras consideraciones, como la legibilidad. Una expresión regular de una línea es definitivamente más bonita de ver. Pero si le preocupa estrictamente la velocidad, es posible que desee considerar esta alternativa.

Michael Martin-Smucker
fuente
17
A los programadores les encanta el aspecto del código, pero ustedes ven su belleza interior.
Ziggy
Enfoque alternativo interesante, ni siquiera se me pasó por la cabeza. ¡Vine aquí solo con expresiones regulares en mente!
ozzy432836
La respuesta que te hace pensar y comprender lo que significa "programación". Utilizo su forma de pensar, en mi respuesta
Oscar Zarrus
42

Compruébalo con una expresión regular.

Javascript regexen no tiene clases de caracteres POSIX, por lo que debe escribir rangos de caracteres manualmente:

if (!input_string.match(/^[0-9a-z]+$/))
  show_error_or_something()

Aquí ^significa comienzo de cadena y $significa final de cadena, y [0-9a-z]+significa uno o más caracteres de 0a 9O de aa z.

Más información sobre Javascript regexen aquí: https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions

Mischa Arefiev
fuente
14
+1 para explicar la expresión regular básica y vincular a una guía, en lugar de darle al usuario una "cadena mágica".
Charles Burns
4
@inor, simplemente puede agregar 'i' al final de la expresión regular para especificar la insensibilidad a mayúsculas y minúsculas, .ie /^[a-z0-9]+$/iy esto cubrirá tanto letras minúsculas como mayúsculas
LJH
33

No es necesario hacerlo de uno en uno. Simplemente haga una prueba para cualquiera que no sea alfanumérico. Si se encuentra uno, la validación falla.

function validateCode(){
    var TCode = document.getElementById('TCode').value;
    if( /[^a-zA-Z0-9]/.test( TCode ) ) {
       alert('Input is not alphanumeric');
       return false;
    }
    return true;     
 }

Si hay al menos una coincidencia de un código no alfanumérico, lo hará return false.

usuario113716
fuente
6

Crearía un método de prototipo de cadena:

String.prototype.isAlphaNumeric = function() {
  var regExp = /^[A-Za-z0-9]+$/;
  return (this.match(regExp));
};

Entonces, el uso sería:

var TCode = document.getElementById('TCode').value;
return TCode.isAlphaNumeric()
Justin
fuente
4
JavaScript
mantenible
2
DJDavid98: No creo que la regla "no modifique los objetos que no posee" se aplica aquí. Justin solo estaba ampliando las capacidades de String, no modificando las funcionalidades existentes. En perspectiva, en el mundo C #, eso se consideraría un uso perfectamente válido de un método de extensión. Incluso si algún día los fabricantes de navegadores implementaran "String.isAlphaNumeric (): boolean", ni la firma ni la acción cambiarían, por lo que no puedo ver ninguna reducción de la capacidad de mantenimiento en este ejemplo en particular. Que algo sea una regla no implica que no haya excepciones.
Risto Välimäki
5
    // On keypress event call the following method
    function AlphaNumCheck(e) {
        var charCode = (e.which) ? e.which : e.keyCode;
        if (charCode == 8) return true;

        var keynum;
        var keychar;
        var charcheck = /[a-zA-Z0-9]/;
        if (window.event) // IE
        {
            keynum = e.keyCode;
        }
        else {
            if (e.which) // Netscape/Firefox/Opera
            {
                keynum = e.which;
            }
            else return true;
        }

        keychar = String.fromCharCode(keynum);
        return charcheck.test(keychar);
    }

Además, este artículo también ayuda a comprender la validación alfanumérica de JavaScript.

Neerajan
fuente
3

Disculpe todo, no hay controversia. Pero para que la comunidad crezca como lo ha hecho yo en estos años, es bueno tomar algunas notas.

La cadena alfanumérica real es como "0a0a0a0b0c0d"y no como "000000"o "qwertyuio".

Todas las respuestas que leí aquí, regresaron trueen ambos casos. Y perdóname, en mi humilde opinión, esto no está bien .

Si quiero comprobar si mi "00000"cadena es alfanum, mi respuesta "humana" es incuestionablemente FALSA.

¿Por qué? Sencillo. No puedo encontrar ningún carácter de letra. Entonces, es una cadena numérica simple [0-9].

Por otro lado, si quisiera verificar mi "abcdefg"cadena, mi respuesta "humana" es incluso FALSA. No veo números, por lo que no es alfanumérico. Solo alfa [a-zA-Z].

La respuesta de Michael Martin-Smucker ha sido esclarecedora.

Sin embargo, su objetivo era lograr un mejor rendimiento en lugar de expresiones regulares. Esto es cierto, usando una forma de bajo nivel hay un mejor desempeño. Pero los resultados son los mismos. Las cadenas "0123456789"(solo numéricas), "qwertyuiop"(solo alfabéticas) y "0a1b2c3d4f4g"(alfanuméricas) regresan TRUEcomo alfanuméricas. Misma /^[a-z0-9]+$/iforma de expresión regular . La razón por la que la expresión regular no funciona es tan simple como obvia. La sintaxis []indica o , no y . Entonces, si es solo numérico o si es solo letras, regex regresa true.

Sin embargo, la respuesta de Michael Martin-Smucker fue esclarecedora. Para mi. Me permitió pensar a "bajo nivel", para crear una función real que procese inequívocamente una cadena alfanumérica. Lo llamé como función relativa de PHP ctype_alnum( editar 2020-02-18: donde, sin embargo, esto verifica O y no Y ).

Aquí está el código:

function ctype_alnum(str) {
  var code, i, len;
    var isNumeric = false, isAlpha = false; //I assume that it is all non-alphanumeric



  for (i = 0, len = str.length; i < len; i++) {
    code = str.charCodeAt(i);


        switch (true){
            case code > 47 && code < 58: // check if 0-9
                isNumeric = true;
                break;
            case (code > 64 && code < 91) || (code > 96 && code < 123): //check if A-Z or a-z
                isAlpha = true;
                break;
            default: // not 0-9, not A-Z or a-z
                return false; //stop function with false result, no more checks

        }

  }

  return isNumeric && isAlpha; //return the loop results, if both are true, the string is certainly alphanumeric
};

... y aquí está la DEMO

Vine a esta discusión porque estaba buscando una alternativa en javascript a la función PHP. No encontré la respuesta "lista para usar", pero como sucede a menudo en Stackoverflow, el concepto de conocimiento y comparación entre sí es algo sublime, que te lleva a pensar en la respuesta de alguien y encontrar juntos la solución que estabas buscando. buscando, pero no pensaste que lo sabías.

¡Y compártelo!

Mejor

Oscar

Oscar Zarrus
fuente
Lo anterior resuelve alphaAndNumeric, no alphaNumeric. return isNumeric || isAlpha;es alphaNumeric. Lo anterior puede ser útil para algunos.
TamusJRoyce
1
@TamusJRoyce por supuesto. Pero imagen para verificar algún número de IVA donde en algunos casos es solo numérico y en otro caso debe ser alfanumérico. Por cierto, solo ahora me doy cuenta, por mi culpa, de que la función PHP relativa prevé OR en lugar de AND. Lo cual es un problema porque tuve que modificar todos los códigos de mis aplicaciones PHP, creando una función ad-hoc que proporcionó el AND
Oscar Zarrus
3

En un ciclo cerrado, probablemente sea mejor evitar las expresiones regulares y codificar sus caracteres:

const CHARS = new Set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
function isAlphanumeric(char) {
    return CHARS.has(char);
}
Malganis
fuente
¿Puede explicar esto?
Lazydeveloper
2
Este código es O (N ^ 2) cuando se escanea una cadena completa en un bucle y dará como resultado un rendimiento mucho peor que incluso las peores soluciones de expresiones regulares presentadas (por ejemplo, un usuario pasa en todas las 'Z, el indexOf () tiene que escanear al final para cada carácter). No solo implica potencialmente la sobrecarga de escanear toda la cadena 0-Z (realizando, en promedio, comparaciones de 18 caracteres por llamada), sino también dos llamadas de función por valor de sobrecarga por carácter de la cadena de origen, ¡un valor de tiempo constante bastante significativo! El código incluso podría introducir una vulnerabilidad DoS dependiendo de dónde se utilice.
CubicleSoft
1
Tienes toda la razón CubicleSoft. Actualicé la respuesta para usar JS Set.
Malganis
0

Para verificar si input_string es alfanumérico, simplemente use:

input_string.match(/[^\w]|_/) == null
Mark Baaijens
fuente