何が!! JavaScriptでは演算子(not not)演算子ですか?


Answers

型変換を行うことは、あまりにも曖昧な方法です。

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

つまり、値をブール値に変換して反転し、反転します。

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

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

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

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

私がこれを見た文脈は、

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



私はこれがC ++の残骸だと思っています。 bool演算子ではありません。

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




ここには、角度のある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になります。 それは本当でしょうか?

requestAnimationFrameがassignedされていた場合、!requestAnimationFrameはtrueとなり、さらに1つの値になります。 それは間違っているだろう




ifwhileステートメントと? 演算子は、実行するコードの分岐を決定するために真理値を使用します。 たとえば、ゼロとNaN番号と空文字列はfalseですが、他の数字と文字列は真です。 オブジェクトはtrueですが、未定義の値とnullは両方ともfalseです。

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

  • xがfalseの場合、 !xtrue!!xfalseです。
  • xが真の値なら、 !xfalseであり、 !!xtrueです。

ブール・コンテキスト( ifwhile 、または? )の最上位レベルで使用すると、 !! オペレータは行動的にノーオペレーションです。 たとえば、 if (x)if (!!x)が同じものを意味するとします。

実用

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

1つの使用法は、オブジェクトをその真理値に不可逆に圧縮することで、コードが大きなオブジェクトへの参照を保持しておらず、生きているようにします。 !!some_big_object!!some_big_object代わりに変数にsome_big_objectすると、ガベージコレクタのためにそれをsome_big_objectます。 これは、オブジェクトや、ブラウザの機能の検出など、 nullや未定義の値などのfalse値を生成する場合に便利です。

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

  • if (a = b)が代入であり、 b真理値を使用した場合、 if (a == b)は等価比較です。
  • if (a & b)がビット単位のANDである場合 if (a && b)は論理ANDです。 2 & 50 (偽の値)です。 2 && 5は真です。

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

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




それは1つの演算子ではなく、2つです。 これは以下に相当し、ブール値に値をキャストする簡単な方法です。

val.enabled = !(!enable);



!! ブール・コンストラクターを使用する場合と似ていますが、おそらくブール関数のようになります。

console.log(Boolean(null)); // Preffered over the Boolean object

console.log(new Boolean(null).valueOf()); // Not recommended for coverting non-boolean values

console.log(!!null); // A hacky way to omit calling the Boolean function, but essentially does the same thing. 


// The context you saw earlier (your example)
var vertical;

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical; 
        // Let's break it down: If vertical is strictly not undefined, return the boolean value of vertical and set it to this.vertical. If not, don't set a value for this.vertical (just ignore it and set it back to what it was before; in this case, nothing).   

        return this.vertical;
}

console.log( "\n---------------------" )

// vertical is currently undefined

console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = 12.5; // set vertical to 12.5, a truthy value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be true anyway
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = -0; // set vertical to -0, a falsey value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be false either way
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

Falsey values in javascript coerce to false , and truthy values coerce to true. Falsey and truthy values can also be used in if statements and will essentially "map" to their corresponding boolean value. However, you will probably not find yourself having to use proper boolean values often, as they mostly differ in output (return values).

Although this may seem similar to casting, realistically this is likely a mere coincidence and is not 'built' or purposely made for and like a boolean cast. So let's not call it that.

Why and how it works

To be concise, it looks something like this: ! ( !null ) . Whereas, null is falsey , so !null would be true . Then !true would be false and it would essentially invert back to what it was before, except this time as a proper boolean value (or even vice versa with truthy values like {} or 1 ).


Going back to your example

Overall, the context that you saw simply adjusts this.vertical depending on whether or not vertical is defined, and if so; it will be set to the resulting boolean value of vertical, otherwise it will not change. In other words, if vertical is defined; this.vertical will be set to the boolean value of it, otherwise, it will stay the same. I guess that in itself is an example of how you would use !! , and what it does.


Vertical I/O Example

Run this example and fiddle around with the vertical value in the input. See what the result coerces to so that you can fully understand your context's code. In the input, enter any valid javascript value. Remember to include the quotations if you are testing out a string. Don't mind the CSS and HTML code too much, simply run this snippet and play around with it. However, you might want to take a look at the non-DOM-related javascript code though (the use of the Example constructor and the vertical variable).

var vertical = document.getElementById("vertical");
var p = document.getElementById("result");

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical;   

        return this.vertical;
}

document.getElementById("run").onclick = function()
{

  p.innerHTML = !!( new Example(eval(vertical.value)).vertical );
  
}
input
{
  text-align: center;
  width: 5em;
} 

button 
{
  margin: 15.5px;
  width: 14em;
  height: 3.4em;
  color: blue;
}

var 
{
  color: purple;
}

p {
  margin: 15px;
}

span.comment {
  color: brown;
}
<!--Vertical I/O Example-->
<h4>Vertical Example</h4>
<code id="code"><var class="var">var</var> vertical = <input type="text" id="vertical" maxlength="9" />; <span class="comment">// enter any valid javascript value</span></code>
<br />
<button id="run">Run</button>
<p id="result">...</p>




After seeing all these great answers, I would like to add another reason for using !! 。 Currenty I'm working in Angular 2-4 (TypeScript) and I want to return a boolean as false when my user is not authenticated. If he isn't authenticated, the token-string would be null or "" . I can do this by using the next block of code:

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



これは2倍の操作でnot 。 最初の! ブール値に変換し、その論理値を反転します。 二番目に! 論理値を反転させる。




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

代わりに、 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




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

あなたは何を得ますか!! 反復可能で標準化された(そしてJSLintに優しい)方法で、複数の変数の真実性を互いに照合する能力です。

単に鋳造する:(

あれは...

  • 0 === falsefalseです。
  • !!0 === falsetrueです。

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

JSLintの指示から "==と!="を参照してください(注:Crockfordは少しでも自分のサイトを動かしています;そのリンクはある時点で死にそうです)

==演算子と!=演算子は比較する前に型変換を行います。 これは '\ t \ r \ n' == 0が真であるために悪いことです。 これは型エラーを隠すことができます。 JSLintは、==が正しく使用されているかどうかを確実に判断できないので、==と!=をまったく使用せず、常により信頼性の高い===と!==演算子を使用することをお勧めします。

価値が真実か偽であることだけを気にしている場合は、短い形式を使用してください。 の代わりに
(foo != 0)

言うだけ
(foo)

代わりに
(foo == 0)

いう
(!foo)

真偽値と数値を比較すると、ブール値が数値にキャストされ( true1キャストされ、 false0キャストされる)、 直感的でない場合があることに注意してください。 この場合、 !! 精神的に有用かもしれない。 ここでも、ブール値ではないブール値をブール値と比較していますが、これは重大な間違いです。 if (-1)がここに行く道だと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をfalseか、WScriptのfalse返しfalse目をそらす。 それは恐ろしいです。

真実性を比較する:)

しかし、もし私が平等な真実性/真実性をチェックする必要がある2つの価値があるとすればどうでしょうか?

私たちがmyVar1 = 0;を持つふりをするmyVar1 = 0; myVar2 = undefined;

  • myVar1 === myVar20 === undefinedであり、明らかに偽です。
  • !!myVar1 === !!myVar2!!0 === !!undefined 、本当です! 同じ真実! (この場合、両方とも「真実性が偽である」。)

だから、本当に "ブールキャスト変数"を使う必要がある唯一の場所は、両方の変数が同じ真実性を持っているかどうかを確認している状況でしょうか? つまり、 使用してください!! もしあなたが2つのヴァールが真実であるか、あるいは両方が偽である (またはそうでない)のか、つまり等しいか(あるいはではない)かを見る必要があれば。

私は、それを大切にして、それほど工夫されていないユースケースを考えることはできません。 多分あなたはフォーム内のフィールドをリンクしているでしょうか?

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日編集:

明示的なブール値を必要とする第三者のライブラリ

面白いケースがあります... !! サードパーティのライブラリで明示的なブール値が必要な場合に役立ちます。

たとえば、JSX(React)のFalseは、単純な虚偽でトリガされない特別な意味を持ちます。 JSXで次のようなものをmessageCountうとした場合、 messageCount intがmessageCountです。

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

...メッセージがゼロのときにリアクションが0になるのを見ると驚くかもしれません。 JSXがレンダリングされないようにするには、明示的にfalseを返す必要があります。 上記のステートメントは、JSXがうまくレンダリングする0を返します。 Count: {messageCount && <div>Get your count to zero!</div>} (またはそれほど工夫されていないもの)

  • 1つの修正には、 0!!0強制するバンバンが含まれ!!0 。これはfalseです。
    {!!messageCount && <div>You have messages!</div>}

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

  • 私は三者で自分自身を偽って扱うのがより快適です -
    {messageCount ? <div>You have messages!</div> : false}

これはJSXの規約であり 、JavaScript固有の規約ではありません

しかし、レンダリングされたJSXで奇妙な0表示された場合は、虚偽の管理を考えてください。




a = 1;
alert(!a) // -> false : a is not not defined
alert(!!a) // -> true : a is not not defined

!a場合、 aが定義されていないかどうかをチェックし、 !!aは変数が定義されているかどうかをチェックします。

!!a !(!a)と同じ!(!a) aが定義されている場合、 atrue!afalse!!atrueです。




いくつかのお茶を醸造する:

!! 演算子ではありません。 それは二重使用です! これは論理的な "not"演算子です。

理論的には:

! 価値がないものの「真実」を決定する:

  • 真実は、 falseが真実でないということtrue (それが理由!false結果がtrue

  • 真実は真実がfalseでないfalse (それが理由!true false !true結果)

!! 価値がないものの「真実」を決定する:

  • 真実は、真実がtrueはないということ true (それが!!true結果true

  • 真実は、 falsefalseはないという false (それは!!false結果です!!false

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

実際には:

動的タイピング (別名「ダックタイピング」)によって、機能の機能性(この場合はプラットフォームの互換性)を検出する簡潔な機能を検討してください。 ユーザーのブラウザがHTML5の<audio>要素をサポートしている場合にtrueを返す関数を記述したいが、 <audio>が定義されていない場合は関数がエラーをスローしないようにしたい。 起こりうるエラーを処理するためにtry ... catchを使用することは望ましくありません。 また 、その機能に関する真実を一貫して明らかにしない関数内のチェックを使用したくない場合あります(たとえば、 document.createElement('audio')はHTML5 <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>と検索するattribute引数を受け取り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を得るための手段が実際には!! 。 うまくいけば、これはばかげてそれをクリアします。




それは!! 演算子は二重否定になります。

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true



私は言及する価値があると思いますが、論理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



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

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

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