web-dev-qa-db-ja.com

JSブールにカスタムプロパティがあるのは悪い習慣ですか?

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

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

それに対して私が想像できる3つの議論があります:

  1. インターフェースが明確でトリッキーではないほうがよい場合は、少し一般的ではありません。
  2. これはわずらわしい議論かもしれませんが、それは少しのエッジケースであるため、JSオプティマイザー、uglifier、VMまたはマイナーなクリーンアップ言語仕様の変更後に、静かに逆火することを想像できます等.
  3. 正確に同じことを行うには、より簡潔で、明確で、一般的な方法があります。

だから私の質問は、追加のプロパティでブール値を使用しないようにする強い理由はありますか?彼らはトリックまたは御馳走ですか?


ツイスト警告をプロットします。

上記は完全に元の質問です。マシュー・クルムリーとセネヴォルデンがどちらも指摘したように、それは誤った(偽物?)前提に基づいています。優れたJSの伝統では、Modernizrが行うことは言語のトリックであり、汚いものです。つまり、falseに設定した場合、TRYINGを実行してもプロップ(サイレントで失敗する)とfalseを維持するプリミティブブールと、カスタムプロップを持つことができるがオブジェクトであるブールオブジェクトは常に真実であるJSになります。 Modernizrは、ブールのfalseまたは真のブールオブジェクトを返します。

私の元の質問では、トリックの動作が異なると想定していたため、最も一般的な回答は、(完全に有効な)コーディング標準の側面を扱います。しかし、私はトリック全体を明らかにする答えが最も役立つ(そして、メソッドの使用に対する最終的な議論も)と思うので、それらの1つを受け入れます。参加者のみなさん、ありがとうございました!

40
konrad

単一の責任などの一般的な設計原則に加えて、最も驚くべきことではありませんが、JavaScript固有の理由で、これはお勧めできません。JavaScriptのbooleanBooleanには大きな違いがあります。一般的なケースでは機能しません。

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

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

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

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

37
Matthew Crumley

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

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

58
candied_orange

私がそれに反対する主な議論は、単一責任の原則です。ブール値は、何かがtrueまたはfalseであるかどうかのみを示す必要があり、理由や方法、その他事。他のオブジェクトを使用してその情報やその他の情報を伝達することは、私の固い信念と実践です。

16
J. Pichardo

これがブール値と呼ばれる理由はすべて、それが真または偽であるという事実であるため、 wikipedia からその目的全体をかなり損なうので、私はその考えを嫌います。

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

(私の太字)

10
user232573

あなたができるというわけではないからといって、JSでは、任意のオブジェクトにプロパティをほとんど付けることができます(ブール値を含む)

それは悪いことですか?

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

それに対する反対のポイントは、ブール値を扱うのに役立つかもしれないいくつかの関連する有用なプロパティを添付することです( Javaはそれを行います )。

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

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

ブール値に格納するべきではないように聞こえますが、ブール値のセット、またはブール値を内部に持つプロパティのセットを使用しています。すべてのフォーマットとサポートの詳細を含むオブジェクトを返すのが、より良いアプローチだと思います。

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

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

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

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

それがModernizrで機能する唯一の理由は付随的です。条件が真の場合にのみ、Booleanオブジェクトを作成します。 falseと評価すると、通常のfalseを返します。つまり、結果がtrueの場合はBooleanobjectsのみを返し、falseの場合は返さないため、機能します。

1
senevoldsen

コンテキストが変わったのは理解していますが、JSを例にして読んだ元の質問に答えたいのですが、JSだけに限定されません。

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

1
jmoreno

与えられた例では、サポートされているすべてのビデオ形式の配列を返すだけできないでしょうか?

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

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

JavaScriptでは、空の配列はfalsyと見なされますが、空でない配列はtruthy、運がよければ、配列に切り替えるだけですべてが以前と同じように機能します 編集いいえ、JavaScript:Pでオブジェクトの真実性を思い出すことができると思ったのはばかげた私です。

0
daniero

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

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

したがって、私の意見では、ブール型のカスタムプロパティを指定することは良い考えではなく、複数の戻りシグニチャを持つメソッドを用意することが良い考えかどうかということではありません。

0
Pieter B