En JS puede devolver un booleano que tenga propiedades personalizadas. P.ej. cuando Modernizr prueba el soporte de video, regresa true
o false
el Boolean devuelto (Bool es un objeto de primera clase en JS) tiene propiedades que especifican qué formatos son compatibles. Al principio me sorprendió un poco, pero luego me empezó a gustar la idea y me pregunté por qué parece ser utilizada con moderación.
Parece una forma elegante de lidiar con todos esos escenarios en los que básicamente desea saber si algo es verdadero o falso, pero puede estar interesado en alguna información adicional que pueda definir sin definir un objeto de devolución personalizado o usar una función de devolución de llamada preparada para aceptar más parámetros De esta manera, conserva una firma de función muy universal sin comprometer la capacidad para devolver datos más complejos.
Hay 3 argumentos en contra que puedo imaginar:
- Es un poco raro / inesperado cuando probablemente sea mejor para cualquier interfaz ser clara y no complicada.
- Esto puede ser un argumento de hombre de paja, pero al ser un caso marginal, me imagino que fracasa en algún optimizador JS, uglifier, VM o después de un pequeño cambio en la especificación del lenguaje de limpieza, etc.
- Hay una forma mejor, concisa, clara y común, de hacer exactamente lo mismo.
Entonces, mi pregunta es ¿hay alguna razón fuerte para evitar el uso de booleanos con propiedades adicionales? ¿Son un truco o un regalo?
La trama tuerce la advertencia.
Arriba está la pregunta original en toda su gloria. Como Matthew Crumley y senevoldsen señalaron, se basa en una premisa falsa (¿falsa?). En la tradición de JS, lo que Modernizr hace es un truco de lenguaje y uno sucio. Se reduce a JS que tiene un bool primitivo que, si se establece en falso, seguirá siendo falso incluso después de INTENTAR agregar accesorios (que falla en silencio) y un objeto booleano que puede tener accesorios personalizados pero ser un objeto siempre es verdadero. Modernizr devuelve un objeto booleano falso o un objeto booleano verdadero.
Mi pregunta original asumía que el truco funciona de manera diferente y, por lo tanto, las respuestas más populares tratan con el aspecto de los estándares de codificación (perfectamente válidos). Sin embargo, encuentro que las respuestas que desacreditan todo el truco son más útiles (y también los argumentos finales contra el uso del método), así que estoy aceptando una de ellas. ¡Gracias a todos los participantes!
null
si no son compatibles y una matriz de formatos si es así. Una lista se considera verdadera en JS, ynull
es falsa.Respuestas:
Además de los principios generales de diseño, como única responsabilidad, y la menor sorpresa, hay una razón para JavaScript específico que no es una buena idea: hay una enorme diferencia entre una
boolean
yBoolean
en JavaScript que le impide trabajar en el caso general.boolean
es un tipo primitivo, no un objeto, y no puede tener propiedades personalizadas. Expresiones comotrue.toString()
trabajo porque detrás de las escenas, se convierte en(new Boolean(true)).toString()
.Boolean
(con una B mayúscula) es un objeto, pero tiene muy pocos buenos usos, y ser utilizado comoboolean
definitivamente no es uno de ellos. La razón de esto es que todoBoolean
es "verdadero", independientemente de su valor , porque todos los objetos se conviertentrue
en un contexto booleano. Por ejemplo, intente esto:Por lo tanto, en general, no hay forma de agregar propiedades a un booleano en JavaScript que aún permita que se comporte de manera lógica. Modernizr puede salirse con la suya porque solo agrega propiedades a los valores "verdaderos", que funcionan de la manera que usted esperaría (es decir, funcionan en declaraciones if). Si el video no es compatible,
Modernizr.video
será realboolean
(con el valorfalse
) y no se le pueden agregar propiedades.fuente
true
en condicional. ¿Por qué usar explícitamente aBoolean
?false
, es estrictamente 'falso' y falso (===
y==
funciona como) PERO, de hecho, no puede agregar accesorios al bool primitivo. La distinción entre Bool y bool aparentemente me abandonó.TypeError
si intenta agregar una propiedad (consulte jsbin.com/yovasafibo/edit?js,console ).Felicidades, has descubierto objetos. La razón para no hacer esto se llama principio de mínimo asombro . Ser sorprendido por un diseño no es algo bueno.
No hay nada de malo en agrupar esta información, pero ¿por qué querrías ocultarla en un Bool? Ponlo en algo que esperarías tener toda esta información. Bool incluido.
fuente
El argumento principal que sostengo en su contra es, el principio de responsabilidad única , un booleano solo debería decir si algo es
true
ofalse
no, por qué o cómo o cualquier otra cosa. Creo y practico firmemente que se deben usar otros objetos para comunicar esa o cualquier otra información.fuente
Boolean
pesar de las travesuras de JavaScript .Dado que la razón por la que se llama valor booleano es el hecho de que es verdadero o falso, no me gusta la idea, ya que prácticamente socava todo su propósito de wikipedia
(mi negrita)
fuente
El hecho de que pueda no significa que deba hacerlo, en JS puede adjuntar propiedades a cualquier objeto (booleanos incluidos)
¿Cómo es eso algo malo?
Por un lado, puede adjuntar más datos irrelevantes a un booleano (según su ejemplo), algo que otro desarrollador no esperará porque ¿por qué debería estar allí? los bools son solo para verdadero y falso.
Un contrapunto para esto es adjuntar algunas propiedades útiles relevantes que pueden ayudarlo a manejar el valor booleano ( Java lo hace ).
Por ejemplo, puede adjuntar una función que convierta el valor booleano en una cadena, un
dirty
indicador que se convirtió en verdadero si se cambió el valor, observadores y devoluciones de llamadas de eventos que pueden activarse cuando se cambia el valor, etc.Suena como algo que no debería almacenarse en un booleano, sino más bien usando un conjunto de booleanos, o un conjunto de propiedades con booleanos dentro de ellos. Creo que un mejor enfoque sería devolver un objeto con todos los formatos y detalles de soporte.
fuente
No puede crear booleanos con propiedades personalizadas en JavaScript. El siguiente error (al menos en FF):
Puede usar o heredar de Boolean, pero como dice Matthew Crumley, da resultados diferentes.
Boolean
es de tipoObject
. Cuando JS necesita el valor booleano de una expresión, convierte utilizando la función de especificaciónToBoolean
, que exige que paraObject
s el resultado sea siempretrue
. Por lo tanto, el valor senew Boolean(false)
evalúa comotrue
! Puede verificar esto en este ejemplo: https://jsfiddle.net/md7abx5z/3/ .La única razón por la que funciona para Modernizr es incidental. Solo crean un
Boolean
objeto cuando la condición es verdadera. Cuando evalúan falso, simplemente regresan ordinariofalse
. Por lo tanto, funciona porque solo devuelvenBoolean
objetos cuando el resultado fue verdadero de todos modos, y nunca cuando es falso.fuente
Entiendo que el contexto ha cambiado, pero me gustaría responder a la pregunta original que leí usando JS como ejemplo, pero no limitado a solo JS.
Agregar propiedades a un valor booleano no sería un problema SI las propiedades tuvieran algo que ver con lo verdadero / falso, no con la variable que contiene el valor. Por ejemplo, agregar un método toYesNoString estaría bien, agregar un numberOfChildren a un valor hasChildren no lo está, y tampoco lo haría preguntasMissed studentPassed. No hay mucho que pueda agregar a un booleano, aparte de varias repeticiones de cadenas, la única propiedad que puedo pensar que tendría sentido es originalExpression. Pero agregarlo no es necesariamente una mala idea en teoría.
fuente
Si miro el código, no se trata realmente de dar propiedades personalizadas booleanas, sino de un método que tiene métodos de retorno con diferentes firmas.
Si es falso, obtiene un falso primitivo y si es verdadero, devuelve un objeto que, por definición, se interpreta como verdadero en javascript.
Entonces, en mi opinión, su pregunta no debería ser si es una buena idea dar propiedades personalizadas booleanas, sino si es una buena idea tener métodos con múltiples firmas de retorno.
fuente
En el ejemplo dado, ¿no podría simplemente devolver una matriz de todos los formatos de video compatibles?
Al menos diría que usar array es algo menos sorprendente que tener "booleanos personalizados".
En Javascript, una matriz vacía incluso se considera falsa , mientras que una matriz no vacía es verdadera , por lo que con un poco de suerte podría cambiar a matrices y todo estaría funcionando como antes deeditar No, tonto por pensar que podría recordar la verdad de objetos en JavaScript: Pfuente
""
tiene typeof"string"
pero en realidad es falso[].length
es falsey si la longitud es0
, no es mucho más mecanografía, y en mi opinión es una mejor indicación de la intención de loif([])
que sería incluso si eso funcionara.