!!〜(チルド/バンバンチルドではない)は、「contains / included」配列メソッド呼び出しの結果をどのように変更しますか?


95

ここのjQuery inArrayページのコメントを読むと、興味深い宣言があります。

!!~jQuery.inArray(elm, arr) 

今、私は二重感嘆符が結果をtype booleanに、の値で変換すると信じていますtrue。私が理解していないのは~、これらすべての中でチルダ()演算子がどのように使用されているのですか?

var arr = ["one", "two", "three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }

ifステートメントのリファクタリング:

if (!!~jQuery.inArray("one", arr)) { alert("Found"); }

壊す:

jQuery.inArray("one", arr)     // 0
~jQuery.inArray("one", arr)    // -1 (why?)
!~jQuery.inArray("one", arr)   // false
!!~jQuery.inArray("one", arr)  // true

また、チルダを前に置くと結果がになることにも気付きました-2

~!!~jQuery.inArray("one", arr) // -2

ここではチルダの目的がわかりません。誰かがそれを説明したり、リソースに私を向けたりできますか?


50
このようなコードを書く人は、キーボードから離れる必要があります。
カークWoll

12
@KirkWoll:なぜ?~jQuery.inArray()実際には非常に便利です-おそらく検索関数-1が失敗して戻る非常に良い理由です(2の補数が偽である唯一の値)。トリックを見たり理解したりすると、それよりも読みやすくなり!= -1ます。
アマダン

9
@Amadan-いいえ。いいえ。真剣に、私はあなたが何かを守っ!!~ているなんて信じられません。
カークWoll

24
問題は、それだけです:「トリック」。if (x != -1)if (~x)私との主な違いは、前者は実際にあなたがやろうとしていることを表現しているということです。後者はあなたが完全に別のことをしたいことを表しています(「64ビットの数値を32ビットの整数に変換し、その整数のビットごとのNOTが真実かどうかを確認してください」)、あなたはたまたまこれで望ましい結果を得ます1つのケース。
JimmiTh

10
>= 0おそらく十分にリートではなかったので、より不可解なもの!!~が使用されました。
ヨッシ

回答:


56

チルダ演算子は、実際にはjQueryの一部ではありません-JavaScript自体ではビット単位のNOT演算子です。

ティルデの大謎(〜)を参照してください。

整数に対してビット単位の論理演算を実行しているため、実験で奇妙な数値が発生しています(これは、私が知っている限り、2の補数またはそのようなものとして格納されている可能性があります...)

2の補数は、数値を2進数で表す方法を説明しています。私は正しかったと思います。


3
修繕!(それを別のリンクに変更しました。奇妙なことに、私の元の回答の後に書かれました...)
pglhall 2013年

121

~前に適用される場合がある特定の理由があります$.inArray

基本的に、

~$.inArray("foo", bar)

行うためのより短い方法です

$.inArray("foo", bar) !== -1

$.inArray最初の引数が見つかった場合は配列内の項目のインデックスを返し、見つからなかった場合は-1を返します。つまり、「この値は配列内にありますか?」というブール値を探している場合、-1は真の値であり、$。inArrayが0(偽の値)を返すため、ブール値の比較を実行できません。 )、それは配列の最初の要素で実際に見つかったことを意味します。

~ビット演算子を適用-1すると0、になり、0は `-1になります。したがって、配列内の値を検出せず、ビットごとのNOTを適用すると、偽の値(0)になり、他のすべての値は0以外の数値を返し、真の結果を表します。

if (~$.inArray("foo", ["foo",2,3])) {
    // Will run
}

そして、それは意図したとおりに機能します。


2
これはブラウザでどの程度サポートされていますか(現在は2014年ですか?)または、完全にサポートされていましたか?
爆発の丸薬

このような基本的な操作が完璧でないと、私は驚きます。
pcarvalho

104

!!~exprそれ以外のfalse場合exprはと評価され-1ますtrue
と同じですがexpr != -1、壊れています*


これは、JavaScriptのビット演算がオペランドを2の補数形式の32ビット符号付き整数に変換するために機能します。したがって!!~-1、次のように評価されます。

   -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1
  ~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
   !0 = true                                     // ! is logical not (true for falsy)
!true = false                                    // duh

以外の値で-1は、少なくとも1つのビットがゼロに設定されます。それを反転すると真実の値が作成されます。!真の値に演算子を2回適用すると、ブール値trueが返されます。

と一緒に使用した.indexOf()場合、結果が正しいかどうかを確認するだけです-1

!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns  0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns  1, the expression evaluates to true

* !!~8589934591falseと評価されるため、これは嫌悪のテストに確実に使用することはできません-1


1
安定したライブラリでは、を使用しても問題はあり~foo.indexOf(bar)ません。文字やパフォーマンスの大幅な節約にはなりませんが、同じ方法で比較的一般的な省略形foo = foo || {}です。
zzzzBov

6
それは問題ではありません...少なくとも誰かがあなたのコードを続行するように求められるまでは。
Salman A


1
@ahsteele、私はそのルールをよく知っていますが、ビット単位の演算子は私が考えることができるすべてのプログラミング言語の一部です。私は、コードを読むことができる誰かが読めるようにプログラミングしようとしています。言語の機能を他の誰かが理解できないからといって使用をやめません。そうでなければ、私はを使用することさえできません!!
zzzzBov

厳密に言えば、>= 0と同じ動作はありません!!~!== -1近いです。
Peter Olson

33

~foo.indexOf(bar)関数が存在しないfoo.contains(bar)ため、表現するための一般的な省略形containsです。

JavaScriptの「偽の」値の概念のため、通常はブール値へのキャストは不要です。この場合は、関数の出力をtrueまたはにするために使用されfalseます。


6
+1この答えは、「なぜ」受け入れられた答えよりも優れていることを説明しています。
nalply

18

jQuery.inArray()-1「見つかりません」を返し、その補数(~)は0です。したがって、「見つかりません」の~jQuery.inArray()場合は偽の値(0)を返し、「見つかりました」の場合は真の値(負の整数)を返します。!!次に、falsy / truthyを実際のブール値false/に形式化しtrueます。したがって、「見つかった」と「見つからない」!!~jQuery.inArray()を与えるでしょう。truefalse


13

~すべての4バイトのためにint、この式に等しいです。-(N+1)

そう

~0   = -(0+1)   // -1
~35  = -(35+1)  // -36 
~-35 = -(-35+1) //34 

3
(たとえば)から、これは常に正しいとは限りません~2147483648 != -(2147483648 + 1)
Frxstrem

10

~オペレータは、ビット単位の補数演算子です。からの整数の結果inArray()は、要素が見つからない場合は-1、またはいくつかの非負の整数です。-1のビット単位の補数(すべて1ビットとしてバイナリで表される)はゼロです。負でない整数のビット単位の補数は常にゼロ以外です。

このように、!!~iとなりますtrue整数「i」は非負整数であり、そして時にfalse「i」が正確であるとき-1。

~常にそのオペランドを整数に強制することに注意してください。つまり、非整数の浮動小数点値と非数値を強制的に整数にします。


10

チルダはビット単位ではありません-値の各ビットを反転します。一般的な経験則として、~数値で使用すると、その符号が反転し、1が減算されます。

したがって、を実行すると~0、-1が得られます(0が反転すると-0、1を引くと-1)。

これは本質的に、常にブール値である値を取得するための非常に精巧で超マイクロ最適化された方法です。


8

あなたが正しい:このコードはfalseindexOf呼び出しが-1 を返すときに返されます。それ以外の場合true

あなたが言うように、次のようなものを使用する方がはるかに賢明でしょう

return this.modifiedPaths.indexOf(path) !== -1;

1
しかし、それはクライアントに送信するためにさらに3バイトです!編集:(ところで冗談で、私のコメントを投稿して、それが明白ではないことに気づきました(これは悲しくて愚かです))
Wesley Murch

@Wesley:それは本当ですが、クライアントがをキャッシュすると仮定して、各クライアントに一度だけ送信する必要があります.js。そうは言っても、送信に余分なバイト>=0はなく!==-1、ビットをいじるバージョンよりもさらに読みやすいというわけではありません。
LukeH

2
誰がここで誰をトロールしているのですか?;)私は、読み取り可能なコードを書くことは、この種の質問を生成する暗号化された事前最適化されたコードよりも優れていると当たり前に思ったと思います。あとで縮小して、読みやすく、理解しやすいコードを記述してください。
ウェズリーマーチ

2
個人的に> -1はもっと読みやすいと思いますが、それはおそらく非常に主観的なものです。
ヨッシ

6

~オペレータは、ビットごとのNOT演算子です。これは、数値をバイナリ形式で受け取り、すべてのゼロを1に、1をゼロに変換することを意味します。

たとえば、バイナリの0は0000000、-1は11111111です。同様に、1は00000001バイナリで、-2は11111110です。


3

私の推測では、数文字短くなっているためです(ライブラリの作者は常にそうしています)。また、ネイティブコードにコンパイルされたときに数マシンサイクルしかかからない演算を使用します(数値との比較ではありません)。

私は別の答えに同意します。これはやり過ぎですが、おそらくタイトなループで意味があるかもしれません(ただし、パフォーマンスゲインの見積もりが必要ですが、そうでない場合は時期尚早の最適化になる可能性があります)。


2

これはビット単位の操作であるため、パスがmodifiedPathsに表示されるかどうかを確認するのが最も高速(計算的に安価)な方法だと思います。


1

として(~(-1)) === 0、そう:

!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false

1
これは正確かもしれませんが、質問者にとって有用な説明ですか?どういたしまして。そもそもそれが理解できなかったら、このような簡潔な答えは役に立たないでしょう。
スパッドリー

この答えは理にかなっていると思います。数学の頭脳がある場合は、各ステップでどの部分が変化しているかを明確に確認できます。それは最高のこの質問への答え?いいえ、でも便利だと思います。+1
テイラーロペス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.