Melhor forma de verificação alfanumérica em Javascript

107

Qual é a melhor maneira de realizar uma verificação alfanumérica em um INPUTcampo em JSP? Anexei meu código atual

<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
fonte
2
Depende de como você define "melhor". A maioria das respostas abaixo sugere regex, que tem um desempenho muito mais lento do que o código original . Eu limpo o seu código um pouco, o que realmente executa muito bem.
Michael Martin-Smucker de

Respostas:

100

Você pode usar este regex /^[a-z0-9]+$/i

Mahesh Velaga
fonte
4
é claro que isso assume que a string vazia ( "") não deve ser correspondida.
zzzzBov
15
ñnão se enquadra no padrão, entretanto, char UTF-8 totalmente válido.
Oybek
8
/ ^ [a-z0-9] + $ / i.test (TCode)
Alex V
3
Testar uma expressão regular parece ser muito mais lento (66% no Chrome 36) do que charCodeAt(). Veja jsPerf e minha resposta abaixo .
Michael Martin-Smucker de
5
Este regex não funciona com letras de caracteres especiais usadas em alguns idiomas, como "ą", "ź", "ć" etc.
Rafał Swacha
79

A inclinação original do autor da pergunta para usar str.charCodeAt(i)parece ser mais rápida do que a alternativa de expressão regular. Em meu teste no jsPerf, a opção RegExp é 66% mais lenta no Chrome 36 (e um pouco mais lenta no Firefox 31).

Esta é uma versão limpa do código de validação original que recebe uma string e retorna trueou 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;
};

Claro, pode haver outras considerações, como legibilidade. Uma expressão regular de uma linha é definitivamente mais bonita de se olhar. Mas se você está estritamente preocupado com a velocidade, pode considerar esta alternativa.

Michael Martin-Smucker
fonte
17
Os programadores adoram a aparência do código, mas você vê sua beleza interna.
Ziggy
Abordagem alternativa interessante - nunca passou pela minha cabeça. Eu vim aqui com apenas regex em mente!
ozzy432836
A resposta que te faz pensar e te faz entender o que significa "programar". Eu uso sua maneira de pensar, em minha resposta
Oscar Zarrus
42

Verifique com um regex.

Javascript regexen não tem classes de caracteres POSIX, então você deve escrever intervalos de caracteres manualmente:

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

Aqui ^significa início da string e $significa fim da string e [0-9a-z]+significa um ou mais caracteres de 0a 9OU de aa z.

Mais informações sobre Javascript regexen aqui: https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions

Mischa Arefiev
fonte
14
+1 para explicar o regex básico e vincular a um guia, em vez de dar ao usuário uma "string mágica".
Charles Burns
4
@inor, você pode simplesmente adicionar 'i' no final da regex para especificar a não diferenciação de maiúsculas e minúsculas, ou seja, /^[a-z0-9]+$/iisso cobrirá as letras maiúsculas e minúsculas
LJH
33

Você não precisa fazer isso um de cada vez. Basta fazer um teste para qualquer um que não seja alfanumérico. Se for encontrado, a validação falha.

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

Se houver pelo menos uma correspondência de um não alfanumérico, isso acontecerá return false.

user113716
fonte
6

Eu criaria um método de protótipo String:

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

Então, o uso seria:

var TCode = document.getElementById('TCode').value;
return TCode.isAlphaNumeric()
Justin
fonte
4
JavaScript
sustentável
2
DJDavid98: Não acho que a regra "não modifique objetos que você não possui" se aplique aqui. Justin estava apenas estendendo as capacidades do String, não modificando as funcionalidades existentes. Para uma perspectiva, no mundo C #, isso seria considerado um uso perfeitamente válido de um método de extensão. Mesmo que algum dia "String.isAlphaNumeric (): boolean" fosse implementado pelos fabricantes de navegadores, nem a assinatura nem a ação mudariam realmente, portanto, não consigo ver nenhuma redução na capacidade de manutenção neste exemplo específico. O fato de algo ser uma regra não significa que não haja exceções.
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);
    }

Além disso, este artigo também ajuda a entender a validação alfanumérica do JavaScript.

Neerajan
fonte
3

Com licença, sem polêmica. Mas para que a comunidade cresça como eu cresci nesses anos, é bom fazer algumas anotações.

A string alfanumérica real é semelhante "0a0a0a0b0c0d"e não semelhante "000000"ou "qwertyuio".

Todas as respostas que li aqui, retornaram trueem ambos os casos. E me perdoe, IMHO, isso não está certo .

Se eu quiser verificar se minha "00000"string é alphanum, minha resposta "humana" é inquestionavelmente FALSE.

Por quê? Simples. Não consigo encontrar nenhuma letra char. Portanto, é uma string numérica simples [0-9].

Por outro lado, se eu quisesse verificar minha "abcdefg"string, minha resposta "humana" seria até FALSA. Não vejo números, portanto não é alfanumérico. Apenas alfa [a-zA-Z].

A resposta de Michael Martin-Smucker foi esclarecedora.

No entanto, seu objetivo era alcançar um melhor desempenho em vez de regex. Isso é verdade, usando uma forma de baixo nível há um melhor desempenho. Mas os resultados são os mesmos. As strings "0123456789"(apenas numéricas), "qwertyuiop"(apenas alfa) e "0a1b2c3d4f4g"(alfanumérico) são retornadas TRUEcomo alfanuméricas. Da mesma /^[a-z0-9]+$/imaneira regex . A razão pela qual a regex não funciona é tão simples quanto óbvia. A sintaxe []indica ou , não e . Portanto, se for apenas numérico ou se for apenas letras, o regex retorna true.

Mas a resposta de Michael Martin-Smucker foi esclarecedora. Para mim. Isso me permitiu pensar em "baixo nível", para criar uma função real que processa inequivocamente uma string alfanumérica. Eu chamei de função relativa do PHP ctype_alnum( editar 2020-02-18: onde, entretanto, isso verifica OR e não AND ).

Aqui está o 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
};

... e aqui está o DEMO

Cheguei a esta discussão porque estava procurando uma alternativa em javascript para a função PHP. Não achei a resposta "pronto para ir", mas como costuma acontecer no Stackoverflow, o conceito de conhecimento e comparação entre si é algo sublime, que te leva a pensar na resposta de alguém e encontrar juntos a solução que você estava procurando, mas você acha que não sabia disso.

E compartilhe!

Melhor

Oscar

Oscar Zarrus
fonte
O acima resolve alphaAndNumeric, não alphaNumeric. return isNumeric || isAlpha;é alphaNumeric. O texto acima pode ser útil para alguns.
TamusJRoyce
1
@TamusJRoyce, é claro. Mas a imagem para verificar algum número de IVA onde em alguns casos é apenas numérico e em outro caso deve ser alfanumérico. A propósito, só agora percebo, minha culpa, que a função PHP relativa prevê OR em vez de AND. O que é um problema porque tive que modificar todos os códigos dos meus aplicativos PHP, criando uma função ad-hoc que fornecia para o AND
Oscar Zarrus
3

Em um ciclo restrito, provavelmente é melhor evitar regex e codificar seus caracteres:

const CHARS = new Set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
function isAlphanumeric(char) {
    return CHARS.has(char);
}
Malganis
fonte
você pode explicar isso
lazydeveloper
2
Este código é O (N ^ 2) ao escanear uma string inteira em um loop e resultará em um desempenho muito pior do que até mesmo as piores soluções regex apresentadas (por exemplo, um usuário passa em todos os 'Z's, o indexOf () tem que varrer para o final para cada personagem). Não só pode incorrer na sobrecarga de varredura de toda a string 0-Z (realizando, em média, 18 comparações de caracteres por chamada), mas também duas chamadas de função com sobrecarga por caractere da string de origem - um valor de tempo constante bastante significativo! O código pode até apresentar uma vulnerabilidade DoS, dependendo de onde é usado.
CubicleSoft
1
Você está absolutamente certo, CubicleSoft. Eu atualizei a resposta para usar JS Set.
Malganis,
0

Para verificar se input_string é alfanumérico, basta usar:

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