とは!! JavaScriptの(ではない)演算子?


3106

次のような2つの感嘆符の形で、認識できない演算子を使用しているように見えるコードをいくつか見ました!!。誰かがこのオペレーターが何をしているのか教えてもらえますか?

私がこれを見た文脈は、

this.vertical = vertical !== undefined ? !!vertical : this.vertical;

945
「bang、bang you're boolean」で覚えてください
Gus

75
念のため、そこに引用されていることを行わないでください。実行if(vertical !== undefined) this.vertical = Boolean(vertical);-何が起こっているのかがより明確で明確になり、不要な割り当てが不要であり、完全に標準であり、(現在のFFおよびChromeで)jsperf.com/boolean-conversion-speedと同じくらい高速です
Phil H 14

73
!! は演算子ではありません。それだけです!演算子を2回。
Vivek 14

11
記録のためだけに、Boolean(5/0)と同じではありません!!5/0
schabluk

63
@schabluk、記録としては、操作の順序がで!!5/0生成される理由ではInfinityなくtrue、で生成される理由Boolean(5/0)です。演算子は演算子よりも優先順位が高いため、-別名- !!5/0と同等です。ダブルバンを使用してブール化する場合は、を使用する必要があります。(!!5)/0true/0!/5/0!!(5/0)
2015年

回答:


2746

に変換Objectbooleanます。それは(例えばfalseyた場合は0nullundefined、など)、それは次のようになりますfalse、それ以外の場合は、true

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

つまり!!、演算子ではなく、!2度の演算子にすぎません。

実際の例「テストIEバージョン」:

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

でも⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false

123
非ブール値を反転ブール値に変換し(たとえば、!5はJSの非偽値であるため!5は偽になります)、次にブール値を反転して元の値をブール値として取得します(したがって!! 5は本当だ)。
チャック

111
それを説明する簡単な方法は次のとおりです。Boolean(5)=== !! 5; 同じキャスト、少ない文字。
ミカ・スナイダー、

39
これは、真の値をブールの真に、偽の値がブールの偽に変換するために使用されます。
thetoolman 2012

13
@Micah Snyderは、JavaScriptでは、ブール値を新しいBoolean()でボックス化するオブジェクトを作成するよりもブールプリミティブを使用する方がよいことに注意してください。違いを確認する例を次に示します。jsfiddle.net
victorvartan

4
私の知る限りでは、このバンバンパターンがあれば(... _文の中に有用ではありません;だけブール値を返すべき関数のreturn文で
RDS

854

これは、型変換を行うためのひどくあいまいな方法です。

!はありません。そう!trueですfalse、そして!falseですtrue!0でありtrue!1ですfalse

つまり、値をブール値に変換してから、それを反転し、次に再び反転しています。

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);

74
!! false = false。!! true = true
cllpse 2009

89
「はるかに理解しやすい」バリアントは、ここで本当に理解しやすいですか?0に対するチェックは、実際の0に対するチェックではありませんが、JavaScriptが0と見なすやや奇妙な値のリストに対するチェック userId ? true : false です。変換が行われていることをより明確にし、userIdの値が明示的に設定されている場合を処理しますundefined
Ben Regenspan

54
私の脳は.. !!varへのデコードに問題がなく、他の方法よりも速く(処理するための命令が少なく)、短くなっています。Boolean(var)!!
adamJLev 2010年

7
@RickyClarksonは、構文的には必要ないため、主に読みやすくするためです。条件式を常に括弧で囲むという規則を使用して、式の残りの部分と区別する場合もあります。
Dave Rager、

8
私はこれに同意しません。userId != 0同様ですnullNaNそしてundefined、しかし、のために偽false。正確にその動作が必要な場合は、おそらくそれを明示する必要があります。しかし、それがとまったく同じように機能したとしても!!userId、これらの値をここでfalseにしたいのか、それともJavascriptの型変換規則の考慮に失敗したのかは明らかではありません。
philh 2014

449

!!expr式の真実性に応じてブール値(trueまたはfalse)を返します。非ブール型で使用するとより意味があります。これらの例、特に3番目以降の例を検討してください。

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!

63
注目に値する:!!new Boolean(false) // true
Camilo Martin

43
...しかしまた!!Boolean(false) // false
Camilo Martin

97
new Boolean(false) はオブジェクトであり、オブジェクトには偽の値が含まれていても真実です。
Salman A

3
はい、私は知っているが、(ほとんどのネイティブコンストラクタという事実を検討しStringNumberDate、など)があまりにも機能として呼び出し可能であることを意味しているが、まだこの場合には結果が違います!
Camilo Martin

4
@CamiloMartin:しばらくすると、プリミティブnew Boolean(false)返されることがわかりました。これが理にかなっているといいのですが。objectBoolean(false) false
Salman A

155

お茶を淹れます:

!!は演算子ではありません。これは、!論理的な「否定」演算子である-の二重使用です。


理論的には:

! 値ではないものの「真実」を決定します。

  • 真実はそうでfalseはありませんtrue(それが理由です!false結果はになりますtrue

  • 真実はそうでtrueはありませんfalse(そのため、!true結果はfalse


!! 値が何であるかの「真実」を決定します ない

  • 真実はそうでtrueはありませ true(そのため、!!true結果はになりますtrue

  • 真実はそうでfalseはありませ false(そのため、!!false結果はになりますfalse


比較で決定したいの、参照自体の値ではなく、参照の値に関する「真実」です。値が期待される場合でも、値についての真実を知りたいユースケースがあります。false(またはfalse)であることを期待している場合、または値がtypeofでないことbooleanます。


実際には:

動的型付け(別名「ダック型付け」)によって機能の機能(この場合はプラットフォームの互換性)を検出する簡潔な関数について考えてみます。trueユーザーのブラウザーがHTML5 <audio>要素をサポートしている場合に返す関数を記述したいのです<audio>が、未定義の場合に関数がエラーをスローするのは望ましくありません。try ... catch考えられるエラーを処理するために使用したくありません(エラーがひどいため)。また、機能の真実を一貫して明らかにしない関数内のチェックを使用したくありません(たとえば、HTML5 がサポートさdocument.createElement('audio')<audio>ていない場合でも呼び出される要素が作成されます<audio>)。


3つのアプローチは次のとおりです。

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

各関数は、 <tag>とan attributeを検索するためのが、比較によって決定されたものに基づいて、それぞれが異なる値を返します。

しかし、待ってください、まだまだあります!

この特定の例で、問題のオブジェクトにプロパティあるかどうかを確認する、もう少しパフォーマンスの高い方法を使用して、プロパティを簡単に確認できることに気付いた方もいるでしょう。これを行うには2つの方法があります。

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

余談です...

まれにこれらの状況が発生する可能性がありますが、trueブール値ではない、おそらく未定義の値から取得する最も簡潔で最もパフォーマンスの高い、したがって最も好ましい手段が実際にを使用するいくつかのシナリオが存在する場合があり!!ます。うまくいけば、これは途方もなくそれをクリアします。


1
完全に素晴らしい答えですが、私は!! 構築します。以来if()これまでのように「truthiness」以来===真-文はすでにブールの表現をキャストし、明示的にブールにテスト関数の戻り値をキャストすることは冗長であるif()文はとにかく行きます。または、実際にブール値になるには真実の式が必要なシナリオがありませtrueんか?
Tom Auger

1
@TomAuger if()ステートメントは偽の値に対してブール値をキャストしますが、オブジェクトにブールフラグを実際に設定したいとします- if()ステートメントのようにキャストしません。たとえば、実際の戻り値のobject.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()いずれかtrueまたはfalse代わりに設定します。別の例としては、おそらくすべての管理者が所属idして0おり、非管理者はid 1以上です。true誰かが管理者でない場合に取得するには、次のようにしますperson.isNotAdmin = !!admin.id。ユースケースはほとんどありませんが、ある場合は簡潔です。
ベニー

103

!!右側の値を同等のブール値に変換します。(貧しい人の「型キャスト」の方法を考えてください)。その意図は通常、コードが変数にどのような値が入っているかではなく、それが「真の」値であることを気にしないことを読者に伝えることです。


4
または、右側のブール値の場合は何もしません。
ダニエルA.ホワイト

3
@ダニエル:!値を右に反転します。ブール値の場合、右端!の値は値を否定し、左端の値は!もう一度否定します。正味の効果は変更がないことですが、ほとんどのエンジンは二重否定のオペコードを生成します。
クレセントフレッシュ

しかし、ポイントは何ですか?私が行う場合、if(0){...Javascriptはすでにこれを知っているので、これは誤りです。なぜ言う方が良いif(!!0){...ですか?
CodyBugstein

重要なのは、その内容を知らない可能性がある変数です。整数または文字列、オブジェクトまたはnull、未定義な​​どである可能性がある場合。これは、存在をテストする簡単な方法です。
mix3d 2016

71

!!foo単項否定演算子を2回適用し、単項プラス+fooを使用して数値にキャストし、空の文字列を連結するのと同様にブール型にキャストするために使用されます''+fooをにキャストするのされます。

これらのハックの代わりに、プリミティブ型に対応するコンストラクター関数(使用せずにnew)明示的に値をキャストます。

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

しかし、その後、instanceofで問題が発生する可能性があります。新しいBoolean(1)instanceof Object-> true !! 1 instanceof Object-> false
Seamus

13
いいえ、あなたがすることはできません:コンストラクタ関数はなしで呼び出されていることを予告new-明示的に私の答えで述べたように
クリストフ・

2
素晴らしい!これは、 "0"の文字列をtrueではなくfalseとして評価する必要がある場合の小さなハックに役立ちます。(つまり、値が文字列として読み取られるため、selectから値を読み取るとき)。したがって、「0」を負(ブールfalse)と見なしたい場合は、次のように仮定x="0"します。x=!!+x; //falseこれは、Boolean(Number(x))数値(または+ x)と同じで、文字列「0」を0に変換します。 (!! x)ブール値に直接キャストします。かんたん簡単!
DiegoDD 2013年

2
@DiegoDDなぜ!!+xvs を選ぶのx !== "0"ですか?
placeybordeaux

@placeybordeauxは、たとえば、値を他のものと比較するかどうかに関係なく、値を変換して他の変数に割り当てたい場合があるためです。
DiegoDD 2016年

67

仕事の半分を行うのに、多くの答えがあります。はい、!!X「Xの真実[ブール値として表される]」と読むことができます。しかし!!、実際には、単一の変数が真実であるか偽であるかを判断するためにそれほど重要ではありません。!!myVar === trueと同じmyVarです。比較する!!X「実際の」ブール値しても、あまり役に立ちません。

あなたが得るもの!!は、複数の変数の真実性をお互いに対してチェックする能力です、繰り返し可能な標準化された(そしてJSLintフレンドリーな)方法で、しです。

単にキャストする:(

あれは...

  • 0 === falseですfalse
  • !!0 === falseですtrue

上記はあまり役に立ちません。if (!0)と同じ結果が得られif (!!0 === false)ます。変数をブール値にキャストし、「真の」ブール値と比較する良いケースは考えられません。

JSLintの指示から「==と!=」を参照してください(注:Crockfordはサイトを少し動かしています。そのリンクはいつか死ぬ可能性があります)。その理由について少し説明します。

==および!=演算子は、比較する前に型強制を行います。これは '\ t \ r \ n' == 0がtrueになるので悪いです。これにより、タイプエラーがマスクされる可能性があります。JSLintは==が正しく使用されているかどうかを確実に判断できないため、==および!=をまったく使用せず、代わりに常により信頼性の高い===および!==演算子を使用することをお勧めします。

値が真実か偽物かだけを気にする場合は、短い形式を使用します。の代わりに
(foo != 0)

言うだけ
(foo)

代わりに
(foo == 0)

いう
(!foo)

ブール値が数値にキャストされるいくつかの直感的でないケースがあることに注意してください(trueにキャストされた1false0数にブール値を比較する場合)。この場合、!!精神的に役立つかもしれません。繰り返しますが、これらは非ブール値をハードタイプのブール値と比較する場合です。つまり、深刻な間違いです。 if (-1)まだここに行く方法です。

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               Original                    Equivalent       Result   
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1 == true) console.log("spam")    if (-1 == 1)       undefined 
 if (-1 == false) console.log("spam")   if (-1 == 0)       undefined 
   Order doesn't matter...                                           
 if (true == -1) console.log("spam")    if (1 == -1)       undefined 
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (!!-1 == true) console.log("spam")  if (true == true)  spam       better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1) console.log("spam")            if (truthy)        spam       still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

そして、あなたのエンジン次第では物事はさらにクレイジーになります。たとえば、WScriptが受賞しました。

function test()
{
    return (1 === 1);
}
WScript.echo(test());

歴史的なWindows jiveあるため、メッセージボックスに-1が出力されます。cmd.exeプロンプトで試してみてください。しかし、WScript.echo(-1 == test())それでも0またはWScriptのが与えられますfalse目をそらす。それは恐ろしいです。

真実の比較:)

しかし、もし私が2つの値を持っている場合、等しい真実性/偽り性をチェックする必要がありますか?

私たちが持っているふり myVar1 = 0;してmyVar2 = undefined;

  • myVar1 === myVar2であり0 === undefined、明らかに誤りです。
  • !!myVar1 === !!myVar2 です !!0 === !!undefined、本当です!同じ真実!(この場合、どちらも「偽りの真実性を持っている」)。

したがって、「boolean-cast変数」を実際に使用する必要がある唯一の場所は、両方の変数が同じ真実性を持っているかどうかを確認している状況である場合でしょう。つまり、2つの変数が両方とも真実であるか、両方とも偽である(またはそうでない)か、つまり等しいかどうかを確認する必要がある場合使用し!!ます。(またはしない)truthiness

私はその手抜きのための素晴らしい、不自然でない使用例を考えることができません。フォームに「リンクされた」フィールドがあるのでしょうか。

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

だから、もしあなたが両方に真実を持っているなら、配偶者の名前と年齢の両方で、あなたは続けることができます。それ以外の場合は、値(またはごく初期に調整された結婚)を持つフィールドが1つだけあり、errorObjectsコレクションに追加のエラーを作成する必要があります。


編集2017年10月24日、2月19日:

明示的なブール値を期待するサードパーティライブラリ

ここに興味深いケースがあります... !!サードパーティのライブラリが明示的なブール値を期待している場合に役立つかもしれません。

たとえば、JSX(React)のFalseには、単純な偽造ではトリガーされない特別な意味があります。JSXで次のようなものを返そうとした場合、intが期待されmessageCountます...

{messageCount && <div>You have messages!</div>}

... 0メッセージがゼロのときにReactがを表示することに驚かれるかもしれません。JSXがレンダリングされないようにするには、明示的にfalseを返す必要があります。上記のステートメントは0、JSXが適切にレンダリングするを返します。それはあなたが持っていなかったCount: {messageCount && <div>Get your count to zero!</div>}(または何か不自然なものではない)とは言えません。

  • 修正の1つは、次のように強制0されるbangbang !!0ですfalse
    {!!messageCount && <div>You have messages!</div>}

  • JSXのドキュメントでは、より明示的に、自己コメントコードを記述し、比較を使用してブール値に強制することを推奨しています。
    {messageCount > 0 && <div>You have messages!</div>}

  • 私は三者で偽りを処理する方が快適です-
    {messageCount ? <div>You have messages!</div> : false}

Typescriptでも同じことが言えます:ブール値を返す関数がある場合(またはブール値に値を割り当てている場合)、[通常は]ブール値のyを返したり割り当てたりすることはできません。強く型付けされたブールでなければなりません。つまり、iff myObjectは強く型付けされreturn !myObject;ブール値を返す関数では機能しますが、機能return myObject;しません。return !!myObjectTypescriptの期待に合わせる必要があります。

Typescriptの例外?myObjectだった場合any、JavaScriptのワイルドウエストに戻り!!、戻り値の型がブール値であっても、なしで返すことができます。

これらはJSXとTypescriptの規則であり、JavaScriptに固有の規則ではないことに注意してください。

しかし0、レンダリングされたJSXに奇妙なs が見られる場合は、緩やかな偽の管理を考えてください。


良い説明。だからあなたは言いますか!! このワーカー機能検出の例では厳密に必要ではありませんか? if (!!window.Worker)
jk7

2
いいえ、必要ありません。真実性とtrue「外部」はでまったく同じように動作しifます。私は試し続けますが、qライブラリの例のように後で値を再利用する場合の読みやすさを除いて、上記の複雑な「真実を比較する」ケース以外の真偽をブール値にキャストすることを好む理由は考えられません。。しかし、それでも、それは情報損失の多いショートカットであり、私はあなたが毎回真実性を評価したほうがよいと私は主張します。
ruffin

Reactが私たちが使い始めた主な理由です!! パターン、しかしそれは非常に便利で再現可能なものです。心配する必要があるのは、何かの真実性や虚偽性だけであり、基礎となるタイプではありません。

コメントのない反対投票はあなたの懸念への対処を難しくします!問題のある箇所を教えていただければ、喜んで対応させていただきます。
ruffin

55

これは、論理的なNOT演算子であり、2回です-何かをブール値に変換するために使用されます。例:

true === !!10

false === !!0

3
一体どうしてそんなことをするの?使用 !演算子をブール値に変換してから===を使用してタイプを比較しますか?タイプセーフがないことを受け入れ、val> 0などを実行してください。
ダレンクラーク

43
@ダーレン:彼は型を比較していません。彼は彼の答えに主張を書くことによって、あなたに結果が何であるかを伝えています。
オービットの


26

それは二重のnot操作です。1つ目!は、値をブール値に変換し、その論理値を反転します。2番目!は、論理値を元に戻します。



23

Boolean()キャスト機能の動作をシミュレートします。1つ目NOTは、指定されたオペランドに関係なくブール値を返します。2番目はNOTそのBoolean値を否定しtrue、変数のブール値を提供します。最終結果は、Boolean()値に対して関数を使用した場合と同じです。


20

!「boolean not」であり、基本的に「enable」の値をその反対のブール値に型キャストします。二番目 !この値を反転します。つまり、!!enable「有効にしない」ことを意味enableし、ブール値としての値を提供します。


18

言及する価値があると思いますが、論理AND / ORと組み合わせた条件はブール値を返しませんが、&&の場合は最後の成功または最初の失敗、||の場合の最初の成功または最後の失敗 条件チェーンの。

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

条件を真のブールリテラルにキャストするために、二重否定を使用できます。

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true

17

!!それはNOT一緒に2回操作を使用し!ています、値をaに変換してboolean逆にします、これはどのように!!動作するかを確認する簡単な例です:

最初に、あなたが持っている場所:

var zero = 0;

次に!0、それを実行すると、ブール値に変換されて評価されますtrue。0はfalsyなので、逆の値を取得してブール値に変換し、に評価されtrueます。

!zero; //true

しかし、値の逆ブールバージョンは必要ないので、もう一度逆にして結果を得ることができます!そのため、別の!

基本的に、 !!私たちが得る値はブール値であり、偽り、真実、文字列などではありません...

つまりBoolean、JavaScriptで関数を使用するようなものですが、値をブール値に変換する簡単で短い方法です。

var zero = 0;
!!zero; //false

15

!!構築物は、そのブール同等に任意のJavaScript式を回す簡単な方法です。

例:!!"he shot me down" === trueおよび!!0 === false


2
重要な区別に非常に近い。重要なのは、それ0 === falseが偽で!!0 === falseあり、真であることです。
ルフィン

14

これは単一の演算子ではなく、2つの演算子です。これは以下と同等であり、値をブール値にキャストする簡単な方法です。

val.enabled = !(!enable);

10

これはC ++の残り物であり、人々が!演算子ではなく、ブール演算子。

したがって、その場合に否定(または肯定)の回答を得るには、最初に!演算子を使用してブール値を取得しますが、正のケースをチェックする場合は!!を使用します。


10

文とオペレータの使用真理値は、実行するために、コードのどの枝を決定します。たとえば、ゼロとNaNの数値と空の文字列はfalseですが、他の数値と文字列はtrueです。オブジェクトは真ですが、未定義の値であり、両方とも偽です。ifwhile?null

二重否定演算子!!は、値の真理値を計算します。これは実際には2つの演算子で、はを!!x意味し!(!x)、次のように動作します。

  • もしはx、偽の値で!xありtrue、かつ!!xありますfalse
  • もしはx、真の値で!xありfalse、かつ!!xありますtrue

ブールコンテキストのトップレベルで使用された場合(ifwhileまたは?)は、!!オペレータが行動何もしません。たとえば、同じことif (x)if (!!x)意味します。

実用化

ただし、いくつかの実用的な用途があります。

1つの使用法は、オブジェクトをその真の値に不可逆的に圧縮して、コードが大きなオブジェクトへの参照を保持せず、それを維持することです。ガベージコレクターの!!some_big_object代わりに、変数に代入することはsome_big_objectできません。これは、オブジェクトまたはnullブラウザの機能検出などの未定義の値などの偽の値を生成する場合に役立ちます。

Cの対応する!!演算子について回答で述べた別の用途は、一般的なタイプミスを探して診断を印刷する「lint」ツールでの使用です。たとえば、CとJavaScriptの両方で、ブール演算のいくつかの一般的なタイプミスは、出力がブール値ではない他の動作を生成します。

  • if (a = b)代入の後に真の値を使用しbます。if (a == b)等価比較です。
  • if (a & b)ビットごとのANDです。if (a && b)論理ANDです。2 & 5is 0(false値); 2 && 5本当です。

!!オペレータは、あなたが書いたことは、あなたが何を意味するのかであることを糸くずのツールを安心させる:この操作は、結果の真理値を取りますか。

3番目の使用法は、論理XORおよび論理XNORを生成することです。CとJavaScriptの両方でa && b、論理AND(両側がtrueの場合はtrue)をa & b実行し、ビットごとのAND を実行します。a || b論理OR(少なくとも1つがtrueの場合はtrue)をa | b実行し、ビットごとのOR を実行します。にはビット単位のXOR(排他的OR)がありますが、論理XOR a ^ bの組み込み演算子はありません(一方のみがtrueの場合はtrue)。たとえば、ユーザーが2つのフィールドのどちらかにテキストを入力できるようにする場合があります。あなたができることは、それぞれを真理値に変換し、それらを比較することです:!!x !== !!y



8

ここにはたくさんの素晴らしい答えがありますが、ここまで読んだことがあれば、「理解する」のに役立ちました。Chrome(など)でコンソールを開き、次のように入力します。

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

当然、これらはすべて!! someThingと入力することと同じですが、括弧を追加するとわかりやすくなります。


8

!!x の略記です Boolean(x)

最初のbangはjsエンジンを強制的に実行しますBoolean(x)が、値を反転するという副作用もあります。したがって、2番目の強打は副作用を元に戻します。


8

すべてのものをブール値にします。

例えば:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true

7

この質問はかなり徹底的に答えられていますが、私はできる限り簡略化して、意味を理解できるようにしたいと思います。できるだけ簡単に把握できます。

JavaScriptを「truthy」と「falsey」値と呼ばれるものがあるため、他の式で評価すると検査されている値または式が実際にではないにも関わらず、真または偽の状態になりますことを表現があるtrueかはfalse

例えば:

if (document.getElementById('myElement')) {
    // code block
}

その要素が実際に存在する場合、式はtrueと評価され、コードブロックが実行されます。

しかしながら:

if (document.getElementById('myElement') == true) {
    // code block
}

...要素が存在していても、真の状態にはならず、コードブロックは実行されません。

どうして?のではdocument.getElementById()この中で真と評価される「truthy」という表現であるif()声明が、それは、実際のブール値ではありませんtrue

この場合の二重の「not」は非常に単純です。それは単に2つnotの背中合わせです。

最初のものは、真または偽の値を単に「反転」して実際のブール型を生成し、次に2番目のものは、それを元の状態に「反転」して元の状態に戻しますが、現在は実際のブール値になります。こうすることで、一貫性を保つことができます。

if (!!document.getElementById('myElement')) {}

そして

if (!!document.getElementById('myElement') == true) {}

期待どおり、両方がtrueを返します。


7

追加したかっただけです

if(variableThing){
  // do something
}

と同じです

if(!!variableThing){
  // do something
}

しかし、何かが定義されていない場合、これは問題になる可能性があります。

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

ここでの秘訣は、&&s のチェーンが最初に検出した誤った値を返すことです。これはifステートメントなどにフィードできます。したがって、b.fooが未定義の場合、undefinedを返し、b.foo.barステートメントをスキップします。エラー。

上記のリターンは未定義いますが、空の文字列、偽、ヌル、0を持っている場合は、それらの値が返されます、我々はチェーンでそれらに遭遇するとすぐに不定- []{}「truthy」の両方であり、私たちは「いわゆるダウン続けます&&チェーン」を右側の次の値に移動します。

PS同じことを行う別の方法はです。これは(b || {}).foo、bが未定義の場合b || {}はであり{}、「未定義」内の値にアクセスしようとする代わりに、空のオブジェクト(エラーなし)の値にアクセスするためです(エラーの原因) )。したがって、(b || {}).fooと同じb && b.foo((b || {}).foo || {}).barあり、と同じb && b.foo && b.foo.barです。


良い点-私の答えを変えた。それは3つのレベルがネストされているオブジェクトでのみ発生します。なぜなら、あなたが言った({}).anythingようにundefined
Ryan Taylor

5

これらのすばらしい答えをすべて見てから、を使用する別の理由を追加したいと思い !!ます。現在、Angular 2-4(TypeScript)で作業しておりfalse、ユーザーが認証されていない場合と同じようにブール値を返したいと思っています。彼が認証されていない場合、トークン文字列はnullまたはになり""ます。これを行うには、次のコードブロックを使用します。

public isAuthenticated(): boolean {
   return !!this.getToken();
}

4

これがangular jsのコードの一部です

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

彼らの意図は、requestAnimationFrameでの機能の可用性に基づいて、rafSupportedをtrueまたはfalseに設定することです。

これは、一般的に次の方法で確認することで実現できます。

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

短い方法を使用している可能性があります!!

rafSupported = !!requestAnimationFrame ;

したがって、requestAnimationFrameに関数が割り当てられている場合、!requestAnimationFrameはfalseになり、もう1つ!それは本当だろう

requestAnimationFrameが未定義で割り当てられた場合、!requestAnimationFrameはtrueになり、もう1つ!それは間違いでしょう


3

JavaScriptの一部の演算子は暗黙的な型変換を実行し、型変換に使用されることもあります。

単項!演算子は、オペランドをブール値に変換し、それを否定します。

この事実により、ソースコードで次のイディオムを確認できます。

!!x // Same as Boolean(x). Note double exclamation mark


3

変数のブール値を返します。

代わりに、Booleanクラスを使用できます。

(コードの説明をお読みください)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

つまり、Boolean(X) = !!X使用中です。

以下のコードスニペットをチェックしてください

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.