Dans JS, vous pouvez renvoyer un booléen ayant des propriétés personnalisées. Par exemple. lorsque Modernizr teste la prise en charge de la vidéo, il renvoie true
ou false
mais le booléen renvoyé (Bool est un objet de première classe dans JS) possède des propriétés spécifiant les formats pris en charge. Au début, cela m'a un peu surpris mais ensuite j'ai commencé à aimer l'idée et j'ai commencé à me demander pourquoi elle semble être utilisée avec parcimonie?
Cela ressemble à une manière élégante de gérer tous ces scénarios où vous voulez essentiellement savoir si quelque chose est vrai ou faux mais vous pouvez être intéressé par des informations supplémentaires que vous pouvez définir sans définir un objet de retour personnalisé ou en utilisant une fonction de rappel préparée pour accepter plus de paramètres. De cette façon, vous conservez une signature de fonction très universelle sans compromettre la capacité de retour de données plus complexes.
Il y a 3 arguments contre cela que je peux imaginer:
Ma question est donc la suivante: y a-t-il de bonnes raisons d'éviter d'utiliser des booléens avec des propriétés supplémentaires? Est-ce un truc ou un régal?
Avertissement de torsion du tracé.
Ci-dessus est la question d'origine en pleine gloire. Comme Matthew Crumley et senevoldsen l'ont tous deux souligné, cela est basé sur une prémisse fausse (fausse?). Dans la tradition de JS, ce que Modernizr fait est un tour de langage et un sale. Cela revient à JS ayant un bool primitif qui, s'il est défini sur false, restera faux même après avoir essayé d'ajouter des accessoires (qui échoue silencieusement) et un objet booléen qui peut avoir des accessoires personnalisés, mais être un objet est toujours véridique. Modernizr renvoie soit un booléen faux, soit un objet booléen véridique.
Ma question d'origine supposait que l'astuce fonctionne différemment et que les réponses les plus populaires concernent donc l'aspect (parfaitement valide) des normes de codage. Cependant, je trouve les réponses démystifiant l'astuce la plus utile (et aussi les arguments ultimes contre l'utilisation de la méthode), donc j'accepte l'une d'entre elles. Merci à tous les participants!
En plus des principes généraux de conception, comme la responsabilité unique et la moindre surprise, il y a une raison spécifique à JavaScript que ce n'est pas une bonne idée: il y a une énorme différence entre un boolean
et Boolean
en JavaScript cela l'empêche de fonctionner dans le cas général.
boolean
est un type primitif, pas un objet, et ne peut pas avoir de propriétés personnalisées. Des expressions comme true.toString()
fonctionnent parce que dans les coulisses, cela se transforme en (new Boolean(true)).toString()
.
Boolean
(avec un B majuscule) est un objet, mais a très peu de bonnes utilisations, et étant utilisé comme boolean
n'en fait certainement pas partie. La raison en est que chaque Boolean
est "vrai", quelle que soit sa valeur, car tous les objets sont convertis en true
dans un contexte booléen. Par exemple, essayez ceci:
var answer = new Boolean(false);
if (answer) {
console.log("That was unexpected.");
}
Donc, en général, il n'y a aucun moyen d'ajouter des propriétés à un booléen en JavaScript qui permet toujours de se comporter de manière logique. Modernizr peut s'en tirer car les seules ajoutent des propriétés aux "vraies" valeurs, qui fonctionnent comme vous vous en doutez (c'est-à-dire qu'elles fonctionnent dans les instructions if). Si la vidéo n'est pas prise en charge du tout, Modernizr.video
sera un boolean
réel (avec la valeur false
) et ne pourra pas avoir de propriétés ajoutées.
Félicitations, vous avez découvert des objets. La raison de ne pas le faire est appelée principe du moindre étonnement . Être surpris par un design n'est pas une bonne chose.
Il n'y a rien de mal à regrouper ces informations, mais pourquoi voudriez-vous les cacher dans un Bool? Mettez-le dans quelque chose que vous attendez d'avoir toutes ces informations. Bool inclus.
L'argument principal contre lequel je m'oppose est le principe de responsabilité unique, un booléen ne devrait dire que si quelque chose est true
ou false
, pas pourquoi ni comment ou tout autre chose. J'ai la ferme conviction et la pratique que d'autres objets devraient être utilisés pour communiquer cette information ou toute autre information.
Puisque toute la raison pour laquelle on l'appelle une valeur booléenne est le fait qu'elle soit vraie ou fausse, je n'aime pas l'idée, car vous sapez à peu près tout son objectif de wikipedia
En informatique, le type de données booléen est un type de données, ayant deux valeurs (généralement notées vrai et faux), destinées à représenter les valeurs de vérité de la logique et de l'algèbre booléenne .
(mon audace)
Ce n'est pas parce que vous le pouvez que vous le devriez, dans JS, vous pouvez à peu près attacher des propriétés à n'importe quel objet (booléens inclus)
En quoi est-ce une mauvaise chose?
D'une part, vous pouvez attacher plus de données non pertinentes à un booléen (selon votre exemple), ce à quoi un autre développeur ne s'attendra pas car pourquoi devrait-il être là?! bools sont juste pour vrai et faux.
Un contre-point pour cela est d'attacher quelques propriétés utiles pertinentes qui peuvent vous aider à gérer la valeur booléenne ( Java le fait ).
Par exemple, vous pouvez attacher une fonction qui convertit la valeur booléenne en chaîne, un indicateur dirty
qui est devenu vrai si la valeur a été modifiée, des observateurs et des rappels d'événements qui peuvent se déclencher lorsque la valeur est modifiée, etc.
mais le Boolean retourné (Bool est un objet de première classe dans JS) a des propriétés spécifiant quels formats sont pris en charge
Cela ressemble à quelque chose qui ne devrait pas être stocké dans un booléen, mais plutôt à l'aide d'un ensemble de booléens ou d'un ensemble de propriétés avec des booléens à l'intérieur. Je pense qu'une meilleure approche serait de retourner un objet avec tous les formats et détails de support.
{
isSomethingSupported: true,
isSomethingElseSupported: false,
....
}
Vous ne pouvez pas faire de booléens avec des propriétés personnalisées en JavaScript. Les échecs suivants (au moins dans FF):
var x = false;
x.foo = "bar";
console.log(x.foo);
Vous pouvez utiliser ou hériter de Boolean, mais comme le dit Matthew Crumley, cela donne des résultats différents. Boolean
est de type Object
. Lorsque JS a besoin de la valeur booléenne d'une expression, il convertit à l'aide de la fonction de spécification ToBoolean
, qui stipule que pour Object
s, le résultat est toujours true
. Ainsi, la valeur new Boolean(false)
est évaluée à true
! Vous pouvez le vérifier dans cet exemple: https://jsfiddle.net/md7abx5z/3/ .
La seule raison pour laquelle cela fonctionne pour Modernizr est accessoire. Ils ne créent un objet Boolean
que lorsque la condition est vraie. Quand ils évaluent faux, ils retournent simplement false
ordinaire. Cela fonctionne donc car ils ne renvoient que des objets Boolean
quand le résultat est vrai de toute façon, et jamais quand il est faux.
Je comprends que le contexte a changé, mais je voudrais répondre à la question initiale que j'ai lue comme utilisant JS comme exemple, mais pas uniquement JS.
L'ajout de propriétés à un booléen ne serait pas un problème SI les propriétés avaient quelque chose à voir avec le vrai/faux, pas avec la variable contenant la valeur. Par exemple, l'ajout d'une méthode toYesNoString serait bien, l'ajout d'un numberOfChildren à une valeur hasChildren ne l'est pas, pas plus que questionsMissed studentPassed. Il n'y a pas grand-chose que vous pourriez ajouter à un booléen, à part diverses représentations de chaînes, la seule propriété à laquelle je pense qui aurait du sens est originalExpression. Mais y ajouter n'est pas nécessairement une mauvaise idée en théorie.
Dans l'exemple donné, ne pourriez-vous pas renvoyer simplement un tableau de tous les formats vidéo pris en charge?
Je dirais au moins qu'utiliser array est un peu moins surprenant que d'avoir des "booléens personnalisés".
En Javascript, un tableau vide est même considéré faux , tandis qu'un tableau non vide est véridique , donc avec un peu de chance, vous pouvez simplement passer aux tableaux et tout fonctionnerait comme avant éditer Non, idiot de penser que je pourrais me souvenir de la véracité des objets en JavaScript: P
Si je regarde le code, il ne s'agit pas vraiment de donner des propriétés personnalisées booléennes mais d'une méthode ayant des méthodes de retour avec des signatures différentes.
S'il est faux, vous obtenez un faux primitif et s'il est vrai, il renvoie un objet qui, par définition, est interprété comme vrai en javascript.
Donc, à mon avis, votre question ne devrait pas être de savoir si c'est une bonne idée de donner des propriétés personnalisées booléennes, mais si c'est une bonne idée d'avoir des méthodes avec plusieurs signatures de retour.