it-swarm.com.de

Ist ein JS-Boolescher Wert mit benutzerdefinierten Eigenschaften eine schlechte Praxis?

In JS können Sie einen Booleschen Wert mit benutzerdefinierten Eigenschaften zurückgeben. Z.B. Wenn Modernizr auf Videounterstützung testet, wird true oder false zurückgegeben, 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 fragte mich, warum sie eher sparsam verwendet zu werden scheint.

Es sieht nach einer eleganten Art aus, mit all den Szenarien umzugehen, in denen Sie grundsätzlich wissen möchten, ob etwas wahr oder falsch ist, aber Sie könnten an zusätzlichen Informationen interessiert sein, die Sie definieren können, ohne ein benutzerdefiniertes Rückgabeobjekt zu definieren oder eine darauf zurückgestellte Rückruffunktion zu verwenden Akzeptiere mehr Parameter. Auf diese Weise behalten Sie eine sehr universelle Funktionssignatur bei, ohne die Kapazität für die Rückgabe komplexerer Daten zu beeinträchtigen.

Es gibt 3 Argumente dagegen, die ich mir vorstellen kann:

  1. Es ist etwas ungewöhnlich/unerwartet, wenn es wahrscheinlich besser ist, wenn eine Benutzeroberfläche klar und nicht knifflig ist.
  2. Dies mag ein Strohmann-Argument sein, aber da es sich um einen Edge-Fall handelt, kann ich mir vorstellen, dass es in einem JS-Optimierer, Uglifier, VM oder nach einer geringfügigen Änderung der Sprachspezifikation für die Bereinigung) leise nach hinten losgeht usw.
  3. Es gibt eine bessere - prägnante, klare und gemeinsame - Methode, um 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 Vergnügen?


Plot Twists Warnung.

Oben ist die ursprüngliche Frage in voller Pracht. Wie Matthew Crumley und Senevoldsen beide betonten, basiert dies 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 lautlos fehlschlägt), falsch bleibt, und ein Boolesches Objekt, das benutzerdefinierte Requisiten haben kann, aber ein Objekt ist, ist immer wahr. Modernizr gibt entweder ein boolesches falsches oder ein wahres boolesches Objekt zurück.

Meine ursprüngliche Frage ging davon aus, dass der Trick anders funktioniert, und daher befassen sich die meisten gängigen Antworten mit dem Aspekt (perfekt gültiger) Codierungsstandards. Allerdings finde ich die Antworten, die den ganzen Trick entlarven, am hilfreichsten (und auch die ultimativen Argumente gegen die Verwendung der Methode), also akzeptiere ich eine davon. Vielen Dank an alle Teilnehmer!

40
konrad

Zusätzlich zu den allgemeinen Gestaltungsprinzipien wie Einzelverantwortung und geringste Überraschung gibt es einen JavaScript-spezifischen Grund, warum dies keine gute Idee ist: Es gibt einen großen Unterschied zwischen einem boolean und Boolean in JavaScript das verhindert, dass es im allgemeinen Fall funktioniert.

boolean ist ein primitiver Typ, kein Objekt und kann keine benutzerdefinierten Eigenschaften haben. Ausdrücke wie true.toString() funktionieren, weil sie sich hinter den Kulissen in (new Boolean(true)).toString().

Boolean (mit einem Großbuchstaben B) ist ein Objekt, hat aber nur sehr wenige gute Verwendungsmöglichkeiten und wird als boolean ist definitiv keiner von ihnen. Der Grund dafür ist, dass jedes Boolean ist "wahr", unabhängig von seinem Wert, weil alle Objekte in einem booleschen Kontext in true konvertiert werden. Versuchen Sie zum Beispiel Folgendes:

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

Im Allgemeinen gibt es also keine Möglichkeit, einem Booleschen Wert in JavaScript Eigenschaften hinzuzufügen, die ein logisches Verhalten ermöglichen. Modernizr kann damit durchkommen, weil nur "wahre" Werte mit Eigenschaften versehen werden, welche Art von Arbeit wie erwartet (d. H. Sie funktionieren in if-Anweisungen). Wenn Video überhaupt nicht unterstützt wird, Modernizr.video ist ein tatsächliches boolean (mit dem Wert false) und kann nicht mit Eigenschaften versehen werden.

37
Matthew Crumley

Herzlichen Glückwunsch, Sie haben Objekte entdeckt. Der Grund, dies nicht zu tun, heißt 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? Setzen Sie es in etwas ein, von dem Sie erwarten würden, dass es all diese Informationen enthält. Bool enthalten.

58
candied_orange

Das Hauptargument, das ich dagegen habe, ist das Prinzip der Einzelverantwortung, ein Boolescher Wert sollte nur sagen, wenn etwas true oder false ist, nicht warum oder wie oder irgendein anderes Ding. Ich bin der festen Überzeugung und Praxis, dass andere Objekte verwendet werden sollten, um diese oder andere Informationen zu kommunizieren.

16
J. Pichardo

Da der ganze Grund, warum es als boolescher Wert bezeichnet wird, die Tatsache ist, dass es wahr oder falsch ist, mag ich die Idee nicht, da Sie ihren ganzen Zweck von wikipedia ziemlich untergraben

In der Informatik ist der Boolesche Datentyp ein Datentyp mit zwei Werten (normalerweise als wahr und falsch bezeichnet) , die die Wahrheitswerte der Logik und der Booleschen Algebra darstellen sollen .

(meine Kühnheit)

10
user232573

Nur weil Sie das können, heißt das nicht, dass Sie es sollten, können Sie in JS so ziemlich jedem Objekt Eigenschaften hinzufügen (einschließlich Boolescher Werte).

Wie ist das eine schlechte Sache?

Einerseits können Sie einem Booleschen Wert (gemäß Ihrem Beispiel) mehr irrelevante Daten hinzufügen, was ein anderer Entwickler nicht erwartet, denn warum sollte er dort sein?! Bools sind nur für wahr und falsch.

Ein Kontrapunkt dafür ist das Anhängen einiger relevanter nützlicher Eigenschaften, die Ihnen beim Umgang mit dem booleschen Wert helfen können ( Java macht das ).

Sie können beispielsweise eine Funktion anhängen, die den booleschen Wert in eine Zeichenfolge konvertiert, ein dirty -Flag, das bei Änderung des Werts auf true gesetzt wurde, Beobachter und Ereignisrückrufe, die ausgelöst werden können, wenn der Wert geändert wird usw.

der zurückgegebene Boolesche Wert (Bool ist ein erstklassiges Objekt in JS) verfügt jedoch über Eigenschaften, die angeben, welche Formate unterstützt werden

Es klingt wie etwas, das nicht in einem Booleschen Wert gespeichert werden sollte, sondern einen Satz von Booleschen Werten oder einen Satz von Eigenschaften mit darin enthaltenen Booleschen Werten verwendet. Ich denke, ein besserer Ansatz wäre, ein Objekt mit allen Formaten und Supportdetails zurückzugeben.

{
    isSomethingSupported: true,
    isSomethingElseSupported: false,
    ....
}
2
svarog

Sie können in JavaScript keine Booleschen Werte mit benutzerdefinierten Eigenschaften erstellen. Folgendes schlägt fehl (zumindest in FF):

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

Sie können Boolean verwenden oder von ihm erben, aber wie Matthew Crumley sagt, gibt es unterschiedliche Ergebnisse. Boolean ist vom Typ Object. Wenn JS den booleschen Wert eines Ausdrucks benötigt, wird er mit der Spezifikationsfunktion ToBoolean konvertiert, die vorschreibt, dass für Objects das Ergebnis immer true ist. Somit ergibt der Wert new Boolean(false)true! Sie können dies in diesem 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, geben sie nur gewöhnliches false zurück. Es funktioniert also, weil sie nur Boolean Objekte zurückgeben, wenn das Ergebnis sowieso wahr war und niemals, wenn es falsch ist.

1
senevoldsen

Ich verstehe, dass sich der Kontext geändert hat, aber ich möchte die ursprüngliche Frage beantworten, die ich als Beispiel für JS gelesen habe, aber nicht nur für JS.

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 questionMissed studentPassed auch nicht. Es gibt nicht viel, was Sie einem Booleschen Wert hinzufügen könnten, außer verschiedenen Zeichenfolgendarstellungen. Die einzige Eigenschaft, die ich mir vorstellen kann, die Sinn macht, ist originalExpression. Aber theoretisch ist das Hinzufügen nicht unbedingt eine schlechte Idee.

1
jmoreno

Könnten Sie im angegebenen Beispiel nicht geben Sie einfach ein Array zurück aller unterstützten Videoformate?

  • Ein leeres Array bedeutet "kein Video Formate unterstützt", was in der Reihenfolge "kein Video unterstützt" bedeutet.
  • Andernfalls wird, wenn ein Video Format unterstützt wird, offensichtlich Video im Allgemeinen unterstützt.

Ich würde zumindest sagen, dass die Verwendung von Arrays etwas weniger überraschend ist als "benutzerdefinierte Boolesche Werte".

In Javascript wird ein leeres Array sogar als falsch betrachtet, während ein nicht leeres Array wahr ist. Mit etwas Glück können Sie also einfach zu Arrays und allem wechseln würde genauso funktionieren wie zuvor edit Nein, dumm mich zu denken, ich könnte mich an die Wahrhaftigkeit von Objekten in JavaScript erinnern: P.

0
daniero

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 falsch und wenn es wahr ist, gibt es ein Objekt zurück, das per Definition in Javascript als wahr interpretiert wird.

Meiner Meinung nach sollte Ihre Frage also nicht sein, ob es eine gute Idee ist, boolesche benutzerdefinierte Eigenschaften anzugeben, sondern ob es eine gute Idee ist, Methoden mit mehreren Rückgabesignaturen zu haben.

0
Pieter B