Existem quatro maneiras de escrever switch JavaScript, você conhece? Se você sabe ou não, eu não sei.
Só existe uma maneira de escrever a instrução switch JavaScript que eu conheço. Mas quando se trata de lidar com ramificações, há muitas maneiras de escrevê-las. O método de escrita de ramificação if pode ser contado como um, o método de escrita de ramificação switch pode ser contado como o segundo e o terceiro é usar o modo de estratégia. Se os operadores condicionais também estiverem incluídos, bem, existem exatamente quatro.
mas o protagonista deste artigo é switch. Todo mundo sabe que switch geralmente é escrito como uma variável ou expressão switch e uma constante case. Bem, por exemplo, para uma pontuação de cem pontos, 90 e acima é considerado excelente, 80 e acima e abaixo de 90 são considerados bons, 60 e acima e abaixo de 80 são considerados qualificados e abaixo de 60 são considerados não qualificados. provavelmente seria escrito assim:
function calcGrade(score ) { linha const = pontuação/10 | mudar (linha) { caso 10: caso 9: retornar "Excelente"; caso 8: retornar "bom"; caso 7: caso 6: retornar “qualificado”; padrão: retornar "não qualificado"; } }
No código, score / 10 | 0
tem o mesmo efeito que Math.floor(score / 10)
, que é dividir por 10 para obter a parte inteira do quociente.
Essa opção é usada muito bem, e o método de arredondamento para evitar o uso de uma longa lista de ramificações if...else também é um truque inteligente.
Mas agora as regras mudaram e o ponto de separação entre qualificados e bons foi reduzido de 80 para 75 pontos. O que devemos fazer?
O método de arredondamento acima ainda é possível, mas desta vez o divisor não é mais 10, mas 5. Da mesma forma, existem muitos mais casos:
É melhor usar 9 casos. se... mais.
É? Na verdade, existe uma maneira mais simples de escrever usando switch:
function calcGrade(score) { mudar (verdadeiro) { pontuação do caso >= 90: retornar "Excelente"; pontuação do caso >= 75: retornar "bom"; pontuação do caso >= 60: retornar “qualificado”; padrão: retornar "não qualificado"; } }
Parece um pouco estranho? Esta não é a constante de case da expressão switch usual, mas exatamente o oposto, a expressão case da constante switch! Se você pegar este programa e executá-lo, descobrirá que não há problema algum. Porque - switch e case são combinados de acordo com ===
, não importa se é uma expressão ou uma constante, ou em outras palavras, switch e case podem ser seguidos por uma expressão!
Sim, expressão!
Portanto, no exemplo acima, alterar switch(true)
switch( 2 > 1)
tem o mesmo efeito.
Ok, minha mente está aberta. Não importa quantas maneiras você pode escrever switch. A próxima coisa a observar é a variante switch.
: vi que C# tem uma expressão switch e estou com ciúmes.
Não se preocupe, tudo em JavaScript pode ser uma expressão... Caso contrário, basta usar IIFE para encapsular uma
função calcGrade(score) { retornar (valor => { mudar (verdadeiro) { valor do caso >= 90: retornar "Excelente"; valor do caso >= 75: retornar "bom"; valor do caso >= 60: retornar “qualificado”; padrão: retornar "não qualificado"; } })(pontuação); }
Observe que score
é usado como parâmetro do IIFE aqui porque, no uso real, pode ser necessário transmitir uma expressão. Neste caso deve ser avaliado antecipadamente e apenas uma vez (para evitar efeitos secundários de substituição).
No entanto, esse encapsulamento obviamente não tem sentido. Se você realmente deseja encapsulá-lo assim, é melhor encapsulá-lo como uma estratégia:
function calcGrade(score) {. return ((valor, regras) => regras.find(({ t }) => t(valor)).v)( pontuação, [ { t: n => n >= 90, v: "Excelente" }, { t: n => n >= 75, v: "Bom" }, { t: n => n >= 60, v: "Qualificado" }, { t: () => verdadeiro, v: "não qualificado" }, ] ); }
Cada estratégia é um objeto contendo um testador ( t
) e um valor ( v
). testador é uma função de julgamento que passa o valor que precisa ser julgado, que é a expressão aqui em switch (表达式)
, e essa expressão também é passada como parâmetro do IIFE após ser avaliada antecipadamente. O processo de aplicação de uma estratégia é simples e rudimentar, que consiste em encontrar a primeira estratégia que satisfaça as condições e retirar o seu valor.
Claro, esta estratégia é um pouco exagerada. Quando você realmente precisa usar uma estratégia, a estratégia geralmente não é um valor, mas sim um comportamento, ou seja, uma função.
Sabemos que na instrução switch cada case está no mesmo escopo, portanto a mesma variável local não pode ser declarada em duas instruções case. Embora agrupar com { }
possa resolver esses problemas, o código não parece muito bom, especialmente tome cuidado para não esquecer break
. Se você usar uma estratégia, ela pode parecer agradável à vista e você não precisa se preocupar com o problema do intervalo:
aqui, para fins de demonstração, no comportamento da estratégia, os resultados serão exibidos primeiro e depois o nível será voltou.
function calcGrade(pontuação) { return ((valor, regras) => regras.find(({ t }) => t(valor)).fn(valor))( pontuação, [ { t: n => n >= 90, fn: pontuação => { const nota = "Excelente"; console.log(nota, pontuação); nota de retorno; } }, { t: n => n >= 75, fn: pontuação => { nota const = "bom"; console.log(nota, pontuação); nota de retorno; } }, { t: n => n >= 60, fn: pontuação => { const nota = "aprovado"; console.log(nota, pontuação); nota de retorno; } }, { t: () => verdadeiro, fn: pontuação => { nota const = "não qualificado"; console.log(nota, pontuação); nota de retorno; } }, ] ); }
O código é realmente um pouco longo porque contém uma lógica de comportamento estratégico. Se realmente vai ser usado como uma expressão switch, a parte da estratégia deve ser uma expressão, não muito longa. No código acima, o comportamento da estratégia é semelhante e pode ser encapsulado em uma função, para que possa ser escrito na forma de uma expressão:
function calcGrade(score) { const printGrade = (nota, pontuação) => { console.log(nota, pontuação); nota de retorno; }; return ((valor, regras) => regras.find(({ t }) => t(valor)).fn(valor))( pontuação, [ { t: n => n >= 90, fn: pontuação => printGrade("Excelente", pontuação) }, { t: n => n >= 75, fn: pontuação => printGrade("Bom", pontuação) }, { t: n => n >= 60, fn: pontuação => printGrade("qualificado", pontuação) }, { t: () => true, fn: pontuação => printGrade("não qualificado", pontuação) }, ] ); }
Parece apresentável agora?
Os códigos acima têm formas diferentes e fazem coisas semelhantes, e não há comparação de qual é o melhor. Não importa o que você goste, você é elegante; não importa o que você não goste, você não é favorecido. Em diferentes situações, basta escolher a abordagem adequada. O código acima usa find()
para encontrar a estratégia. Se filter()
for usado, a história será diferente.