In JS können Sie einen Booleschen Wert mit benutzerdefinierten Eigenschaften zurückgeben. Z.B. Wenn Modernizr die Videounterstützung testet, gibt es zurück, true
oder false
aber der zurückgegebene Boolesche Wert (Bool ist ein erstklassiges Objekt in JS) verfügt über Eigenschaften, die angeben, welche Formate unterstützt werden. Zuerst überraschte es mich ein bisschen, aber dann fing ich an, die Idee zu mögen und mich zu fragen, warum sie eher sparsam verwendet zu werden scheint.
Es sieht aus wie eine elegante Art und Weise, mit all den Szenarien umzugehen, in denen Sie im Grunde wissen möchten, ob etwas wahr oder falsch ist, aber möglicherweise an zusätzlichen Informationen interessiert sind, die Sie definieren können, ohne ein benutzerdefiniertes Rückgabeobjekt zu definieren oder eine Rückruffunktion zu verwenden, für die Sie vorbereitet sind Akzeptieren Sie weitere Parameter. Auf diese Weise behalten Sie eine sehr universelle Funktionssignatur bei, ohne die Fähigkeit zur Rückgabe komplexerer Daten zu beeinträchtigen.
Es gibt drei Argumente dagegen, die ich mir vorstellen kann:
- Es ist etwas ungewöhnlich / unerwartet, wenn es wahrscheinlich besser ist, wenn eine Schnittstelle klar und nicht schwierig ist.
- Dies mag ein Strohmann-Argument sein, aber da es sich um einen Randfall handelt, kann ich mir vorstellen, dass es in einigen JS-Optimierern, Uglifizierern, VMs oder nach einer geringfügigen Änderung der Aufräum-Sprachspezifikationen usw. leise nach hinten losgeht.
- Es gibt eine präzisere, klarere und allgemeinere Methode, genau dasselbe zu tun.
Meine Frage ist also, ob es starke Gründe gibt, die Verwendung von Booleschen Werten mit zusätzlichen Eigenschaften zu vermeiden. Sind sie ein Trick oder ein Leckerbissen?
Plot Twists Warnung.
Oben ist die ursprüngliche Frage in voller Pracht. Wie Matthew Crumley und Senevoldsen beide betonten, basiert es auf einer falschen (falschen?) Prämisse. In feiner JS-Tradition ist Modernizr ein Sprachtrick und ein schmutziger. Es läuft darauf hinaus, dass JS einen primitiven Bool hat, der, wenn er auf false gesetzt ist, auch nach dem VERSUCH, Requisiten hinzuzufügen (was unbemerkt fehlschlägt), und ein boolesches Objekt, das benutzerdefinierte Requisiten haben kann, aber ein Objekt ist, immer wahr. Modernizr gibt entweder Boolean false oder ein wahrheitsgemäßes Boolean-Objekt zurück.
Meine ursprüngliche Frage ging davon aus, dass der Trick anders funktioniert, und daher beschäftigen sich die beliebtesten Antworten mit dem Aspekt der (perfekt gültigen) Codierungsstandards. Allerdings finde ich die Antworten, die den ganzen Trick entlarven, am hilfreichsten (und auch die ultimativen Argumente gegen die Verwendung der Methode), sodass ich eine davon akzeptiere. Vielen Dank an alle Teilnehmer!
null
wenn sie nicht unterstützt werden, und in diesem Fall eine Reihe von Formaten. Eine Liste wird in JS als wahr angesehen undnull
ist falsch.Antworten:
Zusätzlich zu den allgemeinen Gestaltungsprinzipien, wie Einzelverantwortung und am wenigsten überraschend, gibt es einen JavaScript-spezifischen Grund, warum dies keine gute Idee ist: Es gibt einen großen Unterschied zwischen a
boolean
undBoolean
in JavaScript, der verhindert, dass es im allgemeinen Fall funktioniert.boolean
ist ein primitiver Typ, kein Objekt und kann keine benutzerdefinierten Eigenschaften haben. Ausdrücke mögentrue.toString()
Arbeit, denn hinter den Kulissen verwandelt sie sich in(new Boolean(true)).toString()
.Boolean
(mit einem Großbuchstaben B) ist ein Objekt, hat aber nur sehr wenige gute Verwendungszwecke, und esboolean
gehört definitiv nicht dazu , als verwendet zu werden. Der Grund dafür ist, dass jederBoolean
"wahr" ist, unabhängig von seinem Wert , da alle Objektetrue
in einen booleschen Kontext konvertiert werden . Versuchen Sie zum Beispiel Folgendes:Im Allgemeinen gibt es keine Möglichkeit, einem Booleschen Wert in JavaScript Eigenschaften hinzuzufügen, mit denen sich das Verhalten dennoch logisch verhält. Modernizr kann damit durchkommen, weil die einzigen Eigenschaften zu "wahren" Werten hinzufügen, welche Art von Arbeit Sie erwarten würden (dh sie funktionieren in if-Anweisungen). Wenn Video überhaupt nicht unterstützt
Modernizr.video
wird, ist es ein tatsächlichesboolean
(mit dem Wertfalse
) und es können keine Eigenschaften hinzugefügt werden.quelle
true
als bedingt ausgewertet wird. Warum explizit a verwendenBoolean
?false
es streng 'falsch' und falsch (===
und==
funktioniert wie), ABER in der Tat können Sie primitiven Narren keine Requisiten hinzufügen. Die Unterscheidung zwischen Bool und Bool hat mich offensichtlich verunsichert.TypeError
wenn Sie versuchen, eine Eigenschaft hinzuzufügen (siehe jsbin.com/yovasafibo/edit?js,console ).Herzlichen Glückwunsch, Sie haben Objekte entdeckt. Den Grund, dies nicht zu tun, nennt man das Prinzip des geringsten Erstaunens . Von einem Design überrascht zu sein, ist keine gute Sache.
Es ist nichts Falsches daran, diese Informationen zu bündeln, aber warum sollten Sie sie in einem Bool verstecken? Schreiben Sie es in etwas, von dem Sie erwarten, dass es all diese Informationen enthält. Bool enthalten.
quelle
Das Hauptargument, das ich dagegen halte, ist das Prinzip der Einzelverantwortung . Ein Boolescher sollte nur sagen, ob etwas ist
true
oderfalse
nicht, warum oder wie oder irgendetwas anderes. Ich bin der festen Überzeugung und Praxis, dass andere Objekte verwendet werden sollten, um diese oder andere Informationen zu kommunizieren.quelle
Boolean
Ungeachtet der Spielereien von JavaScript .Da der ganze Grund, warum es ein Boolescher Wert genannt wird, die Tatsache ist, dass es wahr oder falsch ist, mag ich die Idee nicht, da Sie so ziemlich den gesamten Zweck von Wikipedia untergraben
(meine Kühnheit)
quelle
Nur weil Sie das nicht können, können Sie in JS praktisch jedem Objekt Eigenschaften zuweisen (einschließlich Boolescher Werte).
Wie ist das eine schlechte Sache?
Einerseits können Sie einem Booleschen Wert (gemäß Ihrem Beispiel) irrelevantere Daten hinzufügen, was ein anderer Entwickler nicht erwartet, denn warum sollte es dort sein ?! Narren sind nur für wahr und falsch.
Ein Gegenpol dazu sind einige relevante nützliche Eigenschaften, die Ihnen beim Umgang mit dem Booleschen Wert helfen können ( Java macht das ).
Sie können beispielsweise eine Funktion anfügen, die den Booleschen Wert in einen String konvertiert, ein
dirty
Flag, das bei Änderung des Werts auf true gesetzt wurde, Watcher und Event-Callbacks, die bei Änderung des Werts ausgelöst werden können usw.Es klingt nach etwas, das nicht in einem Booleschen Wert gespeichert werden sollte, sondern eine Reihe von Booleschen Werten oder eine Reihe von Eigenschaften mit darin enthaltenen Booleschen Werten. Ich denke, ein besserer Ansatz wäre, ein Objekt mit allen Formaten und Unterstützungsdetails zurückzugeben.
quelle
Sie können keine Booleschen Werte mit benutzerdefinierten Eigenschaften in JavaScript erstellen. Folgendes schlägt fehl (zumindest in FF):
Sie können Boolean verwenden oder von Boolean erben, aber wie Matthew Crumley sagt, führt dies zu unterschiedlichen Ergebnissen.
Boolean
ist vom TypObject
. Wenn JS den Booleschen Wert eines Ausdrucks benötigt, konvertiert es ihn mit der SpezifikationsfunktionToBoolean
, die vorschreibt, dass fürObject
s immer das Ergebnis isttrue
. So ist der Wertnew Boolean(false)
ausgewertettrue
! Sie können dies in folgendem Beispiel überprüfen: https://jsfiddle.net/md7abx5z/3/ .Der einzige Grund, warum es für Modernizr funktioniert, ist zufällig. Sie erstellen nur dann ein
Boolean
Objekt, wenn die Bedingung erfüllt ist. Wenn sie false auswerten, kehren sie einfach zu normal zurückfalse
. Es funktioniert also, weil sieBoolean
Objekte nur zurückgeben , wenn das Ergebnis ohnehin wahr ist, und niemals, wenn es falsch ist.quelle
Ich verstehe, dass sich der Kontext geändert hat, aber ich möchte die ursprüngliche Frage, die ich als Beispiel für JS gelesen habe, beantworten, aber nicht nur auf JS beschränkt.
Das Hinzufügen von Eigenschaften zu einem Booleschen Wert wäre kein Problem, wenn die Eigenschaften etwas mit true / false zu tun hätten, nicht mit Variablen, die den Wert enthalten. Zum Beispiel wäre das Hinzufügen einer toYesNoString-Methode in Ordnung, das Hinzufügen einer numberOfChildren zu einem hasChildren-Wert nicht, und auch questionsMissed studentPassed nicht. Es gibt nicht viel, was Sie zu einem Booleschen Wert hinzufügen könnten, außer verschiedenen Zeichenfolgenrepräsentationen. Die einzige Eigenschaft, an die ich denken kann, die Sinn macht, ist originalExpression. Aber es ist theoretisch nicht unbedingt eine schlechte Idee, etwas hinzuzufügen.
quelle
Wenn ich mir den Code anschaue, geht es nicht wirklich darum, boolesche benutzerdefinierte Eigenschaften anzugeben, sondern um eine Methode mit Rückgabemethoden mit unterschiedlichen Signaturen.
Wenn es falsch ist, erhalten Sie ein primitives false und wenn es wahr ist, gibt es ein Objekt zurück, das per Definition in Javascript als wahr interpretiert wird.
Daher sollte Ihre Frage meiner Meinung nach nicht lauten, ob es eine gute Idee ist, boolesche benutzerdefinierte Eigenschaften zu vergeben, sondern ob es eine gute Idee ist, Methoden mit mehreren Rückgabesignaturen zu verwenden.
quelle
Können Sie im Beispiel nicht einfach ein Array aller unterstützten Videoformate zurückgeben?
Ich würde zumindest sagen, dass die Verwendung von Array etwas weniger überraschend ist als die Verwendung von "benutzerdefinierten Booleschen".
In Javascript, wird ein leeres Array sogar als falsy , während ein nicht-leeres Array ist truthy , so mit etwas Glück könnten Sie einfach wechseln zu Arrays und alles so , wie vor der Arbeit wärebearbeiten Nein, mir dumm zu denken , ich die Truthiness erinnern konnte , von Objekten in JavaScript: Pquelle
""
hat Typof,"string"
aber es ist tatsächlich falsch[].length
ist Falsch, wenn Länge ist0
, ist nicht viel mehr Typisierung, und meiner Meinung nach ist dies ein besseres Indiz für Absicht, als es einfachif([])
wäre, selbst wenn dies funktioniert hätte.