カスタムプロパティを持つJSブール値は悪い習慣ですか?


41

JSでは、カスタムプロパティを持つブール値を返すことができます。例えば。Modernizrは、ビデオサポートのためにテストするときに返すtruefalseが、返されたブール(ブール値は、JSでのファーストクラスのオブジェクトである)の形式がサポートされているものを指定するプロパティがあります。最初は少し驚きましたが、そのアイデアが好きになり始め、なぜそれが控えめに使用されているのか疑問に思い始めましたか?

基本的に何かが真であるか偽であるかを知りたいすべてのシナリオを扱うエレガントな方法のように見えますが、カスタム戻りオブジェクトを定義することなく、または準備されたコールバック関数を使用せずに定義できる追加情報に興味があるかもしれませんより多くのパラメーターを受け入れます。この方法により、より複雑なデータを返す能力を損なうことなく、非常に普遍的な関数シグネチャを保持できます。

私が想像できる3つの議論があります:

  1. インターフェイスが明確でトリッキーではない方がおそらく良い場合、それは少し珍しい/予期しないことです。
  2. これはストローマンの議論かもしれませんが、それは少しエッジケースであるため、JSオプティマイザー、uい、VMで静かに裏目に出るか、または言語仕様のマイナーな変更などで静かに裏目に出ることを想像できます。
  3. より正確な、簡潔で、明確で一般的な-まったく同じ方法があります。

だから私の質問は、追加のプロパティでブール値を使用することを避ける強力な理由はありますか?彼らはトリックまたは御treat走ですか?


ねじれ警告をプロットします。

上記は元気な質問です。Matthew Crumleyとsenevoldsenの両方が指摘したように、それは誤った(偽の?)前提に基づいています。優れたJSの伝統では、Modernizrが行うことは言語のトリックであり、汚いものです。要するに、falseに設定された場合、プロップ(サイレントに失敗する)を追加しようとしてもfalseに設定されるプリミティブboolを持つJSと、カスタムプロップを持つことができるが、オブジェクトであるブールオブジェクトは常に真実です。Modernizrは、ブール値falseまたは真実のブール値オブジェクトを返します。

私の元々の質問は、トリックの動作が異なると想定していたため、最も一般的な回答は、コーディング標準の側面(完全に有効)を扱っています。しかし、私はトリック全体を暴く答えが最も役立つと思います(そして、メソッドを使用することに対する究極の引数も)ので、私はそれらの1つを受け入れています。すべての参加者に感謝します!


35
ブール型の拡張は、古典的なwtfです。
-hlovdal

7
JSでは、nullサポートされていない場合は単に返され、サポートされている場合はフォーマットの配列が返されることに注意してください。リストはJSでは真実と見なされ、null偽りです。
jpmc26


3
この質問に答える前に、javascriptでは「ブール値」と「ブール値」に大きな違いがあります。それらは同じものではなく、ブール値を大文字にしない答えは無効です。
ピーターB

2
Modernizrと同じくらい人気のあるライブラリで、このようなものを実際に見てst然と
Chris Nielsen

回答:


38

単一責任のような一般的な設計原理と、少なくとも驚きに加えて、それは良い考えではありませんというのJavaScript固有の理由があります:との間には大きな違いがありますbooleanし、BooleanJavaScriptでは一般的なケースで働くことを防止することをことを。

booleanオブジェクトではなくプリミティブ型であり、カスタムプロパティを持つことはできません。true.toString()仕事のような表現は、舞台裏でに変わるため(new Boolean(true)).toString()です。

Boolean(大文字のBを使用)オブジェクトですが、優れた用途はほとんどbooleanなく、aとして使用されることはそれらの1つではありません。その理由は、すべてのオブジェクトがブールコンテキストで変換されるため、その値関係なく、すべてBooleanが「true」であるためtrueです。たとえば、これを試してください:

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

したがって、一般的に、JavaScriptのブール値にプロパティを追加して、論理的な方法で動作させる方法はありません。Modernizrは、「true」値にプロパティを追加するだけなので、これを回避できます。これは、期待どおりの動作です(つまり、ifステートメントで動作します)。ビデオがまったくサポートされていない場合はModernizr.video、実際booleanの値(値付きfalse)になり、プロパティを追加することはできません。


18
Modernizrのアプローチは、プロパティを持つオブジェクトだけtrueが条件付きで評価されることを考えると、かなり奇妙です。なぜ明示的にaを使用するのBooleanですか?
アルトゥーロトーレスサンチェス

健全な技術的議論をありがとう。私のクイックテストに欠陥があるようです:jsbin.com/hurebi/3/edit?js,console。カスタムのプロップを追加した後もfalse、厳密に「false」で偽りです(===そして==として機能します)が、実際にはプリミティブboolにプロップを追加することはできません。Boolとboolの区別が私を逃げさせたようです。
コンラッド

@ArturoTorresSánchezは、その方法が名目上同じタイプであるためです。
ジャレッド・スミス

1
@ArturoTorresSánchez私は修飾子を追加した理由「名目上」だ:P
ジャレッド・スミス

1
@konrad参考までに、デフォルトでは、JavaScriptは、文句を言わなくてもプリミティブにプロパティを追加できるふりをします。ストリクトモードを使用するとこれが修正され、TypeErrorプロパティを追加しようとするとスローされます(jsbin.com/yovasafibo/edit?js,consoleを参照)。
マシュークランリー

59

おめでとうございます、オブジェクトを発見しました。これをしない理由は、最小の驚きの原理と呼ばれます。デザインに驚かれることは良いことではありません。

この情報をまとめることには何の問題もありませんが、なぜそれをBoolに隠したいのでしょうか?これらすべての情報があると思われるものに入れてください。ブールが含まれています。


1
LOLはい、私は質問の中で明らかな代替手段としてオブジェクトに言及しました。JSの弱いタイピングオブジェクトはそれほど驚くことではありませんが、それでも混乱を招きますが、とにかくドキュメントをチェックする必要がありますが、最小限の驚きの原則は良い点です。使用方法に関しては、Modernizrは良い例です:真の結果/偽の結果が均一なテストの大規模なスイートがあり、たった今、より多くの情報を渡す必要があります。ライブラリ全体に重大な変更を加えて、ブール値の周りにほとんど冗長なラッパーを作成するか、boolを拡張します。IMOはそれほど愚かではありません。
コンラッド

1
使用方法についてもう少し。ブール値を返すことに固執する場合は、any()、all()、filter()などのリスト操作にすべての関数を簡単に渡すことができます。少し型破りであるという犠牲を払って、JSでの強い型付けや正式なインターフェースの欠如を回避します。
コンラッド

1
「型にはまらない」というのは、私にとって強い議論のようには思えません。
ロバートハーベイ

質問を編集しました。ここに、最小限の驚きの原則があります。:-)
コンラッド

16

それに対して、メイン引数Iホールドは、ある単一責任の原則何かがある場合は、ブール値だけ言うべきtrueか、falseなぜないか、どのようにまたは任意の他の事。私は、他のオブジェクトを使用してその情報または他の情報を伝達する必要があると固く信じています。


javascriptでブール値またはブール値(大文字のB)を意味しますか?違いがあります。
ピーターB

しかし、これを定義するオブジェクトや他の何かがある場合、それは間違いなく同じ原則に違反していないでしょうか?
ケーシー

1
@Caseyいいえ。そのオブジェクトの目的は元のブール値と異なるためです。そして、例として、トランザクションの状態と理由を伝えることはただ一つの責任です。
J. Pichardo

1
@Casey問題は、この情報を単独で含むことはSRPの違反ではないということです。ブール値がすでに持っている責任と組み合わせた場合にのみ問題になります-trueまたはfalseを表します。Booleanそれにもかかわらず、JavaScriptの悲劇。
ジェイコブライレ

10

ブール値と呼ばれる全体の理由はそれが真か偽かという事実なので、あなたはウィキペディアからその全体の目的をかなり損なっているので、私はその考えを嫌います

コンピューターサイエンスでは、ブールデータ型は、論理値とブール代数の真理値を表すための 2つの値(通常はtrueとfalseで示される)を持つデータ型です。

(私の太字)


1
正しいが、それ以外の場合は必要となる場合がある
-svarog

8
@svarogで唯一必要なのは、コードの未熟なデザイナーです。bool などを返す必要がある場合は、クラス、タプル、リスト、または特定のコードに適合するその他のものに戻します。
マシューロック

yesを返す場合
-svarog

質問はブールプリミティブではなくブールオブジェクトに関するものだと思います。オブジェクトは値ではありません。
ピーターB

1
trueまたはfalse以外の値をとることができる場合、ブール値でありません。名前を与えられた、それはばかげています。
役に立たない

2

できるというわけではないからといって、JSではプロパティを任意のオブジェクトにアタッチできます(ブール値を含む)

それはどうですか?

一方では、(例ごとに)より関連性の低いデータをブール値に添付できます。これは、他の開発者が、なぜそこにあるべきなのかを予期しないものです!ブール値は真と偽のためだけです。

それに対する反論点は、ブール値の処理に役立つ関連する有用なプロパティを添付することです(Javaはそれを行います)。

たとえば、ブール値を文字列に変換する関数dirty、値が変更されたときにtrueになったフラグ、値が変更されたときに起動できるウォッチャーおよびイベントコールバックなどをアタッチできます。

ただし、返されるブール(BoolはJSのファーストクラスオブジェクト)には、サポートされる形式を指定するプロパティがあります

ブール値に保存されるべきではなく、ブール値のセット、またはブール値が内部にあるプロパティのセットを使用するもののように聞こえます。より良いアプローチは、すべての形式とサポートの詳細を含むオブジェクトを返すことだと思います。

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

1
ブールまたはブール(大文字のB)を意味しますか?
ピーターB

1

JavaScriptのカスタムプロパティでブール値を作成することはできません。次の失敗(少なくともFFでは):

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

ブールを使用することも、ブールから継承することもできますが、Matthew Crumleyによると、異なる結果が得られます。Booleanあるタイプ Object。JSが式のブール値を必要とする場合、仕様関数を使用して変換しますToBoolean。これはObject、結果が常にであることを要求しtrueます。したがって、値new Boolean(false)true!と評価されます。:あなたは、この例ではこれを確認することができますhttps://jsfiddle.net/md7abx5z/3/

Modernizrで機能する唯一の理由は偶発的です。Boolean条件が真の場合にのみオブジェクトを作成します。彼らが偽を評価するとき、彼らはただ普通を返しfalseます。とにかく、結果がtrueの場合のみBoolean オブジェクトを返し、falseの場合は決して返さないため、動作します。


1

コンテキストが変更されたことは理解していますが、JSを例として使用していると読んだ元の質問に答えたいと思いますが、JSだけに限定されません。

プロパティがブール値に追加されても、プロパティが値を保持する変数ではなくtrue / falseに関係がある場合は問題になりません。たとえば、toYesNoStringメソッドを追加しても問題ありません。hasChildren値にnumberOfChildrenを追加しても問題はなく、questionMissed studentPassedも同様です。さまざまな文字列表現以外にブール値に追加できるものはそれほど多くありません。私が考えることができる唯一のプロパティはoriginalExpressionです。しかし、それに追加することは必ずしも理論上悪い考えではありません。


0

コードを見ると、これは実際にはブール型のカスタムプロパティを与えることではなく、異なるシグネチャを持つ戻りメソッドを持つメソッドについてです。

falseの場合、プリミティブなfalseを取得し、trueの場合、JavaScriptでtrueとして解釈されるオブジェクトを返します。

だから、私の意見では、あなたの質問はブールカスタムプロパティを与えることは良いアイデアかどうかではなく、複数のリターンシグネチャを持つメソッドを持つことは良いアイデアかどうかです。


0

指定された例では、サポートされているすべてのビデオ形式の配列返すことはできませんか?

  • 空の配列は「ビデオ形式がサポートされていない」ことを意味し、順番に「ビデオがサポートされていない」ことを意味します。
  • それ以外の場合、ビデオ形式がサポートされていれば、明らかにビデオ全般がサポートされています。

少なくとも、配列を使用することは、「カスタムブール値」を使用することよりもやや意外であると言えます。

JavaScriptでは、空の配列がさえ考えられているfalsy非空の配列であるのに対し、truthyので、いくつかの幸運をあなただけの配列に切り替えることができ、すべての直前として働くことになり、 編集愚かな私、私はtruthinessを覚えている可能性が考えについて、ハズレJavaScriptのオブジェクトの:P


空の配列は、ifステートメントでfalseと評価されません。if([])console.log( 'not false'); たとえば、Chromeで「falseではない」と出力します。typeof [] === 'object'なので、空の配列は偽物ではありません。参考としてdeveloper.mozilla.org/en-US/docs/Glossary/Truthyをご覧ください。
joshp

@joshpおっと、あなたは正しい、私の悪い。修正
daniero

とはいえ、タイプのことで何かが証明されるかどうかはわかりません。""typeofを持っている"string"が、それは実際にfalsyある
daniero

1
一方、[].length長さがの場合はfalse 0であり、タイピングはそれほど多くありません。そして、私の意見では、if([])それが機能していても、意図のより良い指標です。
-IllusiveBrian

@daniero typeof [] === 'object'についてのポイントは、すべてのオブジェクトが真実であり、新しいブール値(false)であることです。一部のプリミティブ型(たとえば、文字列 ""および番号0)は偽物ですが、typeofに関する限りオブジェクトではありません。覚えておくための別の方法です。それは何かを証明することではありません。証明は、仕様またはテストのうち、どちらを選択してもかまいません。
joshp
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.