Eu tenho uma declaração condicional muito longa como a seguinte:
if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
// do something.
}
Eu queria saber se eu poderia refatorar essa expressão / declaração de uma forma mais concisa.
Alguma idéia de como conseguir isso?
javascript
if-statement
FlyingCat
fonte
fonte
in
?||
. (2)switch
declarações. (3) regex. (4)~
. jsperf.com/if-statements-test-techsinRespostas:
Coloque seus valores em uma matriz e verifique se o item está na matriz:
Se um navegador que você suporta não possui o
Array#includes
método, você pode usar esse polyfill .Breve explicação do
~
atalho til:Em vez de verificar se o resultado
indexOf
é>= 0
, existe um pequeno atalho:Aqui está o violino: http://jsfiddle.net/HYJvK/
Como é que isso funciona? Se um item for encontrado na matriz,
indexOf
retornará seu índice. Se o item não foi encontrado, ele retornará-1
. Sem entrar em muitos detalhes,~
é um operador NOT bit bit , que retornará0
apenas para-1
.Eu gosto de usar o
~
atalho, pois é mais sucinto do que fazer uma comparação no valor de retorno. Eu gostaria que o JavaScript tivesse umain_array
função que retorne um booleano diretamente (semelhante ao PHP), mas isso é apenas uma ilusão ( atualização: agora funciona).includes
. Veja acima). Observe que o jQueryinArray
, enquanto compartilha a assinatura do método PHP, na verdade imita aindexOf
funcionalidade nativa (que é útil em diferentes casos, se o índice for o que você realmente procura).Nota importante: O uso do atalho til parece estar envolvido em controvérsias, pois alguns acreditam veementemente que o código não é suficientemente claro e deve ser evitado a todo custo (consulte os comentários nesta resposta). Se você compartilha o sentimento deles, deve se ater ao
.indexOf(...) >= 0
solução.Um pouco mais de explicação:
Inteiros em JavaScript são assinados, o que significa que o bit mais à esquerda é reservado como o bit de sinal; uma bandeira para indicar se o número é positivo ou negativo, com um
1
negativo.Aqui estão alguns exemplos de números positivos no formato binário de 32 bits:
Agora, aqui estão os mesmos números, mas negativos:
Por que combinações tão estranhas para os números negativos? Simples. Um número negativo é simplesmente o inverso do número positivo + 1; adicionar o número negativo ao número positivo deve sempre gerar
0
.Para entender isso, vamos fazer uma aritmética binária simples.
Aqui está como adicionaríamos
-1
a+1
:E aqui está como adicionaríamos
-15
a+15
:Como obtemos esses resultados? Fazendo acréscimos regulares, da maneira como fomos ensinados na escola: você começa na coluna mais à direita e soma todas as linhas. Se a soma for maior que o maior número de um dígito (que é decimal
9
, mas em binário1
), transportamos o restante para a próxima coluna.Agora, como você notará, ao adicionar um número negativo ao número positivo, a coluna mais à direita, que não é todos os
0
s, sempre terá dois1
s, que, quando somados, resultarão em2
. A representação binária de dois seres10
, carregamos a1
para a próxima coluna e colocamos um0
para o resultado na primeira coluna. Todas as outras colunas à esquerda têm apenas uma linha com a1
, portanto, a1
passagem da coluna anterior será adicionada novamente2
, que será transferida ... Esse processo se repete até chegar à coluna mais à esquerda, onde o1
transportador não tem para onde ir, então transborda e se perde, e ficamos com0
s por toda parte.Este sistema é chamado de Complemento 2 . Você pode ler mais sobre isso aqui:
Representação do complemento 2 para números inteiros assinados .
Agora que o curso intensivo do complemento 2 terminou, você notará que esse
-1
é o único número cuja representação binária está1
em todo o lado.Usando o
~
operador NOT bit a bit, todos os bits em um determinado número são invertidos. A única maneira de0
voltar a inverter todos os bits é se começarmos com1
todos os lados.Então, tudo isso foi um longo modo de dizer que
~n
só voltará0
sen
for-1
.fonte
!== -1
de qualquer maneira concebível? A lógica booleana explícita não é mais apropriada do que implicitamente usar a falsey-ness de zero?!= -1
.Você pode usar a instrução switch com fall thru:
fonte
||
) no Chrome. Veja jsperf.com/if-statements-test-techsinUsando Science: você deve fazer o que o idfah disse e isso para obter a velocidade mais rápida, mantendo o código curto:
ISSO É MAIS RÁPIDO DO QUE O
~
Métodohttp://jsperf.com/if-statements-test-techsin (conjunto superior: Chrome, conjunto inferior: Firefox)
Conclusão:
Se houver possibilidades poucos e você sabe que certas pessoas são mais prováveis de ocorrer do que você obter o máximo desempenho fora
if ||
,switch fall through
eif(obj[keyval])
.Se houver possibilidades muitas , e qualquer uma delas pode ser a que mais ocorre, em outras palavras, você não sabe o que é mais provável de ocorrer do que obtém o máximo desempenho da pesquisa de objeto
if(obj[keyval])
eregex
se isso se encaixa.http://jsperf.com/if-statements-test-techsin/12
Eu atualizarei se algo novo surgir.
fonte
switch case
método é o mais rápido?if ( ...||...||...)...
obj["itemX"]
é extremamente rápido se n for grande. Basicamente, o que é rápido depende do contexto. Diverta-se.Se você estiver comparando com seqüências de caracteres e houver um padrão, considere usar expressões regulares.
Caso contrário, suspeito que tentar reduzi-lo apenas ofuscará seu código. Considere simplesmente envolver as linhas para torná-lo bonito.
fonte
(test.type == 'itemf' && foo.mode == 'detailed')
)Usar um objeto como uma matriz associativa é uma coisa bastante comum, mas como o JavaScript não tem um conjunto nativo, você também pode usar objetos como conjuntos baratos.
fonte
if
instrução @dcarson OP ocupa 78 caracteres se você remover todo o espaço em branco. Mina leva 54 se você escrevê-lo como este:test.type in {"itema":1,"itemb":1,"itemc":1,"itemd":1}
. Fundamentalmente, ele usa quatro caracteres para cada duas minas usadas para cada chave adicional.ou se os itens não forem tão uniformes, então:
fonte
Respostas excelentes, mas você pode tornar o código muito mais legível envolvendo uma delas em uma função.
É uma declaração complexa, se você (ou outra pessoa) ler o código dentro de alguns anos, estará pesquisando para encontrar a seção para entender o que está acontecendo. Uma declaração com esse nível de lógica de negócios fará com que você tropece por alguns segundos enquanto trabalha no que está testando. Onde um código como este, permitirá que você continue a digitalização.
Nomeie sua função explicitamente para que fique óbvio imediatamente o que você está testando e seu código será muito mais fácil de digitalizar e entender.
fonte
// CheckIfBusinessRuleIsTrue
?Você pode colocar todas as respostas em um conjunto Javascript e depois chamar
.contains()
o conjunto.Você ainda precisa declarar todo o conteúdo, mas a chamada em linha será mais curta.
Algo como:
fonte
Uma das minhas maneiras favoritas de fazer isso é com uma biblioteca como underscore.js ...
http://underscorejs.org/#some
fonte
contains
é sem dúvida uma solução melhor do quesome
some
é uma função no protótipo Array no EC5.outra maneira ou outra maneira incrível que eu encontrei é essa ...
é claro que, como você pode ver, isso leva as coisas um passo adiante e facilita o acompanhamento da lógica.
http://snook.ca/archives/javascript/testing_for_a_v
usando operadores como ~ && || ((), ()) ~~ só funciona se o seu código quebrar mais tarde. Você não saberá por onde começar. Portanto, a legibilidade é GRANDE.
se necessário, você pode torná-lo mais curto.
e se você quiser fazer inverso
fonte
Basta usar uma
switch
declaração em vez de umaif
declaração:Switch
também funciona mais rápido do que comparar muitos condicionais dentro de umif
fonte
Para listas muito longas de strings, essa idéia salvaria alguns caracteres (sem dizer que eu recomendaria na vida real, mas deve funcionar).
Escolha um caractere que você sabe que não ocorrerá em seu test.type, use-o como um delimitador, cole todos em uma sequência longa e pesquise:
Se suas seqüências de caracteres estiverem mais restritas, você pode até omitir os delimitadores ...
... mas você deve ter cuidado com falsos positivos nesse caso (por exemplo, "embite" corresponderia nessa versão)
fonte
Para facilitar a leitura, crie uma função para o teste (sim, uma função de uma linha):
então chame-o:
fonte
Eu acho que existem 2 objetivos ao escrever esse tipo de condição.
Como tal, algumas vezes o nº 1 pode ser o mais rápido, mas usarei o nº 2 para facilitar a manutenção posteriormente. Dependendo do cenário, geralmente optarei por uma variação da resposta de Walter.
Para começar, tenho uma função disponível globalmente como parte da minha biblioteca existente.
e quando eu realmente quiser executar uma condição if semelhante à sua, criaria um objeto com uma lista dos valores válidos:
Não é tão rápido quanto uma declaração switch / case e é um pouco mais detalhado do que alguns dos outros exemplos, mas geralmente recebo a reutilização do objeto em outras partes do código, o que pode ser bastante útil.
Pegando carona em uma das amostras jsperf feitas acima, adicionei este teste e uma variação para comparar velocidades. http://jsperf.com/if-statements-test-techsin/6 A coisa mais interessante que notei é que certos combos de teste no Firefox são muito mais rápidos que o Chrome.
fonte
Isso pode ser resolvido com um simples loop for:
Usamos a primeira seção do loop for para inicializar os argumentos que você deseja corresponder, a segunda seção para interromper a execução do loop for e a terceira seção para fazer com que o loop saia eventualmente.
fonte