Em JS, você pode retornar um booleano com propriedades customizadas. Por exemplo. quando o Modernizr testa o suporte a vídeo, ele retorna true
ou false
o Booleano retornado (Bool é um objeto de primeira classe em JS) possui propriedades que especificam quais formatos são suportados. No começo, me surpreendeu um pouco, mas depois comecei a gostar da ideia e comecei a me perguntar por que ela parece ser usada com moderação?
Parece uma maneira elegante de lidar com todos os cenários em que você basicamente quer saber se algo é verdadeiro ou falso, mas pode estar interessado em algumas informações adicionais que você pode definir sem definir um objeto de retorno personalizado ou usar uma função de retorno de chamada preparada para aceite mais parâmetros. Dessa forma, você mantém uma assinatura de função muito universal sem comprometer a capacidade de retornar dados mais complexos.
Existem 3 argumentos contra isso que posso imaginar:
- É um pouco incomum / inesperado quando provavelmente é melhor para qualquer interface ser clara e não complicada.
- Este pode ser um argumento simples, mas, com um pouco de dificuldade, posso imaginar que ele sai pela culatra em algum otimizador de JS, uglifier, VM ou após uma pequena alteração na especificação da linguagem de limpeza etc.
- Existe uma maneira melhor - concisa, clara e comum - de fazer exatamente o mesmo.
Então, minha pergunta é: existem razões fortes para evitar o uso de booleanos com propriedades adicionais? Eles são um doce ou travessura?
A plotagem distorce o aviso.
Acima está a pergunta original em plena glória. Como Matthew Crumley e senevoldsen apontaram, é baseado em uma premissa falsa (falsidade?). Na tradição JS, o que o Modernizr faz é um truque de linguagem e um truque sujo. Tudo se resume a JS tendo um bool primitivo que, se definido como false, permanecerá falso, mesmo depois de TENTAR adicionar adereços (que falham silenciosamente) e um objeto booleano que pode ter adereços personalizados, mas ser um objeto é sempre verdadeiro. Modernizr retorna um objeto booleano booleano falso ou verdadeiro.
Minha pergunta original assumiu que o truque funciona de maneira diferente e, portanto, as respostas mais populares lidam com o aspecto (perfeitamente válido) dos padrões de codificação. No entanto, acho as respostas que desmembram todo o truque mais útil (e também os argumentos finais contra o uso do método), por isso estou aceitando uma delas. Obrigado a todos os participantes!
null
se não forem suportados e uma matriz de formatos, se houver. Uma lista é considerada verdadeira em JS enull
é falsa.Respostas:
Além dos princípios gerais de design, como a responsabilidade única e menor surpresa, há uma razão específica de JavaScript que não é uma boa idéia: há uma enorme diferença entre um
boolean
eBoolean
em JavaScript que o impede de trabalhar no caso geral.boolean
é um tipo primitivo, não um objeto e não pode ter propriedades personalizadas. Expressões comotrue.toString()
trabalho, porque nos bastidores, ele se transforma(new Boolean(true)).toString()
.Boolean
(com letra maiúscula B) é um objeto, mas tem muito poucos usos bons, e ser usado como umboolean
definitivamente não é um deles. A razão para isso é que tudoBoolean
é "verdadeiro", independentemente do seu valor , porque todos os objetos são convertidostrue
em um contexto booleano. Por exemplo, tente o seguinte:Portanto, em geral, não há como adicionar propriedades a um booleano em JavaScript que ainda permita que ele se comporte de maneira lógica. O Modernizr pode se safar disso, pois apenas adiciona propriedades a valores "verdadeiros", que tipo de trabalho como você esperaria (ou seja, eles funcionam nas instruções if). Se o vídeo não for suportado,
Modernizr.video
será um valor realboolean
(com o valorfalse
) e não poderá ter propriedades adicionadas a ele.fonte
true
condicional. Por que usar explicitamente umBoolean
?false
ele, é estritamente 'falso' e falso (===
e==
funciona como), mas, na verdade, você não pode adicionar adereços ao bool primitivo. A distinção entre Bool e bool fugiu de mim, aparentemente.TypeError
se você tentar adicionar uma propriedade (consulte jsbin.com/yovasafibo/edit?js,console ).Parabéns, você descobriu objetos. A razão para não fazer isso é chamada de princípio de menor espanto . Ser surpreendido por um design não é uma coisa boa.
Não há nada errado em agrupar essas informações, mas por que você deseja ocultá-las em um Bool? Coloque-o em algo que você esperaria ter todas essas informações. Bool incluído.
fonte
O principal argumento que sustento é que, o princípio da responsabilidade única , um booleano só deve dizer se algo é
true
oufalse
não, por que ou como ou qualquer outra coisa. É minha firme convicção e prática que outros objetos sejam usados para comunicar essa ou qualquer outra informação.fonte
Boolean
Apesar das travessuras do JavaScript .Como todo o motivo pelo qual ele é chamado de valor booleano é verdadeiro ou falso, não gosto da ideia, pois você prejudica todo o seu propósito na wikipedia
(meu negrito)
fonte
Só porque você pode, não significa que deveria, em JS você pode praticamente anexar propriedades a qualquer objeto (incluindo booleanos)
Como pode ser uma coisa ruim?
Por um lado, você pode anexar dados mais irrelevantes a um booleano (por exemplo), algo que outro desenvolvedor não espera, porque por que deveria estar lá ?! bools são apenas para verdadeiro e falso.
Um contraponto é anexar algumas propriedades úteis relevantes que podem ajudá-lo a lidar com o valor booleano ( Java faz isso ).
Por exemplo, você pode anexar uma função que converte o valor booleano em uma string, um
dirty
sinalizador que se tornará verdadeiro se o valor for alterado, observadores e retornos de chamada de eventos que podem disparar quando o valor for alterado etc.Parece algo que não deve ser armazenado em um booleano, mas usando um conjunto de booleanos ou um conjunto de propriedades com booleanos dentro deles. Eu acho que uma abordagem melhor seria retornar um objeto com todos os formatos e detalhes de suporte.
fonte
Você não pode criar booleanos com propriedades personalizadas em JavaScript. A seguinte falha (pelo menos em FF):
Você pode usar ou herdar do booleano, mas como Matthew Crumley diz, ele fornece resultados diferentes.
Boolean
é do tipoObject
. Quando o JS precisa do valor booleano de uma expressão, ele é convertido usando a função de especificaçãoToBoolean
, que exige que, paraObject
s, o resultado seja sempretrue
. Assim, o valor énew Boolean(false)
avaliado comotrue
! Você pode verificar isso neste exemplo: https://jsfiddle.net/md7abx5z/3/ .O único motivo pelo qual o Modernizr funciona é incidental. Eles só criam um
Boolean
objeto quando a condição é verdadeira. Quando avaliam falso, apenas retornam comunsfalse
. Portanto, funciona porque eles retornamBoolean
objetos apenas quando o resultado é verdadeiro, e nunca quando é falso.fonte
Entendo que o contexto mudou, mas gostaria de responder à pergunta original, que li como JS como exemplo, mas não apenas a JS.
Adicionar propriedades a um booleano não seria um problema se as propriedades tivessem algo a ver com true / false, não com a variável que mantinha o valor. Por exemplo, adicionar um método toYesNoString seria bom, adicionar um numberOfChildren a um valor hasChildren não é e nem o questionMissed studentPassed. Não há muito que você possa adicionar a um booleano, além de várias representações de string, a única propriedade em que consigo pensar que faria sentido é originalExpression. Mas adicionar a isso não é necessariamente uma má ideia em teoria.
fonte
Se eu olhar o código, não se trata realmente de fornecer propriedades personalizadas booleanas, mas de um método que possui métodos de retorno com assinaturas diferentes.
Se for falso, você obtém um falso primitivo e, se for verdadeiro, retorna um objeto que, por definição, é interpretado como verdadeiro em javascript.
Portanto, na minha opinião, sua pergunta não deve ser se é uma boa ideia fornecer propriedades personalizadas booleanas, mas se é uma boa ideia ter métodos com várias assinaturas de retorno.
fonte
No exemplo dado, você não poderia simplesmente retornar uma matriz de todos os formatos de vídeo suportados?
Eu diria pelo menos que usar array é um pouco menos surpreendente do que ter "booleanos personalizados".
Em Javascript, um array vazio é mesmo considerado Falsas , enquanto uma matriz não-vazia é truthy , então com alguma sorte você pode simplesmente mudar para matrizes e tudo estaria trabalhando como anteseditar Não, bobo me para pensar que eu poderia lembrar o truthiness de objetos em JavaScript: Pfonte
""
tem typeof,"string"
mas na verdade é falso[].length
é falsey se o comprimento é0
, não é muito mais digitado e, na minha opinião, é uma indicação melhor da intenção do queif([])
seria mesmo se isso funcionasse.