¿Es un JS Boolean tener propiedades personalizadas una mala práctica?

41

En JS puede devolver un booleano con propiedades personalizadas. P.ej. cuando Modernizr prueba la compatibilidad con video, devuelve true o false pero el Booleano devuelto (Bool es el 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 comencé a preguntarme por qué parece que se usa con moderación.

Parece una forma elegante de lidiar con todos esos escenarios en los que básicamente quiere saber si algo es verdadero o falso, pero puede interesarle cierta información adicional que puede definir sin definir un objeto de devolución personalizado o usar una devolución de llamada. Función 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:

  1. Es un poco raro / inesperado cuando probablemente es mejor que cualquier interfaz sea clara y no complicada.
  2. Este puede ser un argumento de hombre de paja, pero al ser un caso un poco perturbador, puedo imaginarlo silenciosamente contraproducente en algunos JS optimizer, uglifier, VM o después de un pequeño cambio en la especificación del idioma, etc.
  3. Hay una forma mejor, concisa, clara y común de hacer exactamente lo mismo.

Entonces, mi pregunta es: ¿existen razones sólidas para evitar el uso de booleanos con propiedades adicionales? ¿Son un truco o una golosina?

Advertencia sobre los giros del trazado.

Arriba está la pregunta original en toda su gloria. Como lo señalaron Matthew Crumley y senevoldsen, se basa en una premisa falsa (¿falsa?). En la fina tradición de JS, lo que hace Modernizr es un truco de lenguaje y uno sucio. Se reduce a que JS tiene un bool primitivo que, si se establece en false, seguirá siendo falso incluso después de TRYING para agregar props (que falla silenciosamente) y un objeto booleano que puede tener props personalizados pero ser un objeto siempre es verdadero. Modernizr devuelve un objeto booleano falso o un objeto booleano de verdad.

Mi pregunta original asumió que el truco funciona de manera diferente y, por lo tanto, las respuestas más populares tratan el aspecto de los estándares de codificación (perfectamente válido). Sin embargo, me parece que las respuestas que desacreditan todo el truco son las más útiles (y también los argumentos finales en contra del uso del método), así que acepto una de ellas. ¡Gracias a todos los participantes!

    
pregunta konrad 09.01.2017 - 05:57

9 respuestas

38

Además de los principios generales de diseño, como la responsabilidad única y la menor sorpresa, hay una razón específica de JavaScript que no es una buena idea: hay una gran diferencia entre un boolean y un Boolean en JavaScript que lo impide De trabajar en el caso general.

boolean es un tipo primitivo, no un objeto, y no puede tener propiedades personalizadas. Las expresiones como true.toString() funcionan porque detrás de escena, se convierte en (new Boolean(true)).toString() .

Boolean (con un capital B) es un objeto, pero tiene muy pocos usos adecuados, y el uso como boolean definitivamente no es uno de ellos. El motivo es que cada Boolean es "verdadero", independientemente de su valor , porque todos los objetos se convierten a true en un contexto booleano. Por ejemplo, prueba esto:

var answer = new Boolean(false);
if (answer) {
  console.log("That was unexpected.");
}

Por lo tanto, en general, no hay forma de agregar propiedades a un booleano en JavaScript que aún permita que se comporte de una manera lógica. Modernizr puede salirse con la suya porque las únicas propiedades se agregan a los valores "verdaderos", qué tipo de trabajo podría esperarse (es decir, funcionan en sentencias if). Si el video no es compatible en absoluto, Modernizr.video será un boolean real (con el valor false ), y no se le pueden agregar propiedades.

    
respondido por el Matthew Crumley 09.01.2017 - 17:55
59

Enhorabuena, has descubierto objetos. La razón para no hacer esto se llama el principio de de menos 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 esconderla en un Bool? Ponlo en algo que esperas tener toda esta información. Bool incluido.

    
respondido por el candied_orange 09.01.2017 - 06:43
16

El principal argumento que sostengo es el principio de responsabilidad única , un booleano solo debe decir si algo es true o false , no por qué o cómo o cualquier otra cosa. Es mi firme creencia y práctica que otros objetos deben usarse para comunicar esa o cualquier otra información.

    
respondido por el J. Pichardo 09.01.2017 - 06:44
10

Dado que toda 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 menoscaba su propósito. de wikipedia

  

En informática, el tipo de datos booleano es un tipo de datos, que tiene dos valores (normalmente denotados como verdadero y falso), pretende representar los valores de verdad de la lógica y el álgebra booleana .

(mi negrilla)

    
respondido por el Orangesandlemons 09.01.2017 - 11:51
2

El hecho de que puedas no significa que debas hacerlo, en JS puedes agregar propiedades a cualquier objeto (incluidos los booleanos)

¿Cómo es eso algo malo?

Por un lado, puede adjuntar más datos irrelevantes a un Boolean (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 punto contrario es adjuntar algunas propiedades útiles relevantes que pueden ayudarlo a lidiar con el valor booleano ( Java hace eso ).

Por ejemplo, puede adjuntar una función que convierte el valor booleano en una cadena, un indicador dirty que se convirtió en verdadero si se cambió el valor, observadores y devoluciones de llamada de eventos que pueden activarse cuando se cambia el valor, etc.

  

pero el Booleano devuelto (Bool es un objeto de primera clase en JS) tiene propiedades que especifican qué formatos son compatibles

Suena como algo que no debería almacenarse en un Booleano, sino en 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.

{
    isSomethingSupported: true,
    isSomethingElseSupported: false,
    ....
}
    
respondido por el svarog 09.01.2017 - 11:18
1

No puedes hacer booleanos con propiedades personalizadas en JavaScript. Lo siguiente falla (al menos en FF):

    var x = false;
    x.foo = "bar";
    console.log(x.foo);

Puedes usar, o heredar de Boolean, pero como dice Matthew Crumley, da diferentes resultados. Boolean es de tipo Object . Cuando JS necesita el valor booleano de una expresión, la convierte mediante la función de especificación ToBoolean , que exige que para Object s el resultado sea siempre true . Por lo tanto, el valor new Boolean(false) se evalúa como true ! Puede verificar esto en este ejemplo: enlace .

La única razón por la que funciona para Modernizr es incidental. Solo crean un objeto Boolean cuando la condición es verdadera. Cuando evalúan falso, simplemente devuelven false ordinario. Así que funciona porque solo devuelven Boolean objetos cuando el resultado fue verdadero de todos modos, y nunca cuando es falso.

    
respondido por el senevoldsen 09.01.2017 - 18:39
1

Comprendo que el contexto ha cambiado, pero me gustaría responder a la pregunta original que leí como ejemplo de cómo usar JS, pero sin limitarme a JS.

Agregar propiedades a un booleano, no sería un problema SI las propiedades tuvieran algo que ver con el verdadero / falso, no con la variable que mantiene el valor. Por ejemplo, agregar un método aYesNoString estaría bien, agregar un númeroOfChildren a un valor de hasChildren no lo es, y tampoco lo harían las preguntas del estudiante perdido. No hay mucho que pueda agregar a un booleano, aparte de varias representaciones de cadenas, la única propiedad que puedo pensar que tenga sentido es la expresión original. Pero agregarlo no es necesariamente una mala idea en teoría.

    
respondido por el jmoreno 20.01.2017 - 03:17
0

Si veo el código, no se trata realmente de otorgar propiedades personalizadas booleanas, sino de un método que tiene métodos de devolución con firmas diferentes.

Si es falso, obtienes un falso primitivo y si es verdadero, devuelve un objeto que, por definición, se interpreta como verdadero en javascript.

Por lo tanto, en mi opinión, su pregunta no debería ser si es una buena idea darle propiedades personalizadas booleanas, sino si es una buena idea tener métodos con múltiples firmas de retorno.

    
respondido por el Pieter B 09.01.2017 - 19:06
0

En el ejemplo dado, ¿no podrías devolver una matriz de todos los formatos de video compatibles?

  • Una matriz vacía significa "no se admiten formatos de video ", que en orden significa "no se admiten video ".
  • De lo contrario, si se admite cualquier formato de video, obviamente, video en general se admite.

Al menos diría que el uso de array es algo menos sorprendente que tener "booleanos personalizados".

En Javascript, una matriz vacía se considera incluso falsy , mientras que una matriz no vacía es truthy , por lo que con un poco de suerte, simplemente puede cambiar a las matrices y todo funcionaría igual que antes editar No, tonto por pensar que podría recordar la veracidad de los objetos en JavaScript: P

    
respondido por el daniero 09.01.2017 - 18:22

Lea otras preguntas en las etiquetas