チルドが式の前にある場合、チルドは何をしますか?


回答:


266

~あるビット演算子オペランドのすべてのビットを反転です。

たとえば、数値がである場合1IEEE 754浮動小数点のバイナリ表現(JavaScriptによる数値の処理方法)は次のようになります...

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

したがって~、そのオペランドを32ビット整数に変換します(JavaScriptのビット演算子はそれを行います)...

0000 0000 0000 0000 0000 0000 0000 0001

負の数の場合、2の補数で格納されます。すべてのビットを反転して1を加えます。

...そして、すべてのビットを反転します...

1111 1111 1111 1111 1111 1111 1111 1110

それで、それの使用は何ですか?いつそれを使うのでしょうか?

それはかなりの数の用途があります。低レベルのものを書いているなら、それは便利です。アプリケーションのプロファイルを作成してボトルネックが見つかった場合は、ビット単位のトリックを使用することで(より大きなバッグの1つの可能なツールとして)、パフォーマンスを向上させることができます。

また、(一般的に)不明だトリックオンにするindexOf()見つかっに戻り値をtruthy(ながら見られないようfalsy、)と人々はしばしば32ビットに番号を切り捨て(と、それを2倍にすることにより、その小数点以下を落とし、その副作用のためにそれを使用します実質的に同じMath.floor()正の数です)。

それが何に使われているのかすぐにはわからないので、私は不明確だと言います。一般的に、コードはそれを読んでいる他の人と明確に通信したいとします。使用~することはクール見えるかもしれませんが、一般的にそれ自体のためにはあまりにも賢いです。:)

また、JavaScriptにはとがあるためArray.prototype.includes()、関連性は低くなっていますString.prototype.includes()。これらはブール値を返します。ターゲットプラットフォームがサポートしている場合は、文字列または配列内の値の存在をテストするためにこれを優先する必要があります。


2
嫌な言葉は正しいですか?それがうまくいけば、私はそれを言語のイディオムと呼びます。イディオムはたくさんあります。あなたがそれらを学ぶと、それらは不明確ではありません。リスト内包表記は、知らない場合は明確ではなく、より詳細なループで実現できるが、Pythonプログラマにそれらを使用しないように依頼することはありません。同様にvalue = value || default、いつJavaScriptを使用できるか、使用できないかがわかっている限り、JavaScriptは一般的で有効なイディオムです。
gman 2014年

3
@gman誰かが使用してもしなくてもかまいません。リスト内包表記(言語機能)とこれを比較することは、実際には同じことではないと思います(余分な文字を入力しないようにするための賢明な方法)。厄介な言葉が厳しすぎると思われる場合は、お気軽に私の回答を編集してください。
アレックス

2
多分より一般的な例はv = t ? a : b;です。var v; if (t} { v = a; } else { v = b; }通常、5行以上にまたがって分割されるよりもはるかに明確であり、通常はvar v = b; if (t) { v = a; }4行以上に分割される場合よりも明確です。しかし、私? :は2番目または3番目の方法を好むオペレーターに精通していない多くの人々を知っています。最初の方が読みやすいです。私は一般原則に同意し、コードを明確にし、ハックを使用しません。私~v.indexOf('...')はそれを学んだ後、私は非常に明確に見えると思います。
gman 2014年

9
多くの開発者がいる大企業で作業している場合、コードを明確に記述し(英語)、十分に文書化する必要があります。ガベージコレクションを備えた言語での高レベルのコーディングのポイントは、バイナリ演算について考えないようにすることであり、多くのフロントエンド開発者は、自分のベルトの下でアセンブリ言語の経験すらありません。
user2867288

3
私は~慣用句を呼ばないでしょう。技術的には言語仕様の一部ですが、一般的に使用される言語の一部ではありません。
2018

108

前にそれを使用して indexOf()式のと、直接返される数値インデックスの代わりに、真実/偽の結果が得られます。

戻り値がの場合-1、それ~-1はがすべて1ビットのストリングである0ため-1です。ゼロ以上の値を入力すると、ゼロ以外の結果になります。したがって、

if (~someString.indexOf(something)) {
}

if「something」が「someString」にあるときにコードを実行させます。使用しようとすると.indexOf()ブール値として直接と、ゼロが返される場合があるため、機能しません(「何か」が文字列の先頭にある場合)。

もちろん、これも機能します:

if (someString.indexOf(something) >= 0) {
}

そしてそれはかなり不思議ではありません。

時々これも見るでしょう:

var i = ~~something;

この~ように演算子を2回使用すると、文字列を32ビット整数にすばやく変換できます。1つ目~は変換を行い、2つ目~はビットを元に戻します。もちろん、数値に変換できないものに演算子を適用するNaNと、結果が得られます。(編集 -実際に~は最初に適用されるのは2番目ですが、あなたはそのアイデアを理解します。)


2
少しずつ否定したくない人のために~、整数で実行した場合はに等しくなり-(x + 1)ます。
FABRICIOマット

ええと、ご存知のように、負の数値も負のブール値を最初に返す必要があります。しかし、JSのもう1つが失敗すると思いますか?
wwaawaw 2012

7
@adlwalrusは、0存在することfalseと非存在でないことの伝統はtrue、少なくとも70年代のCやおそらく他の多くの当時のシステムプログラミング言語にさかのぼります。それはおそらくハードウェアが機能する方法に由来します。多くのCPUは、操作後にゼロビットを設定し、それに対応する分岐命令をテストします。
2012

4
これを32ビットのintに変換するより速い方法は| 0です。その場合、その操作は1つだけです。
アレックス

@alexは確かに、ランタイムが完全に~~同じ方法の単純なアプリケーションを解釈しないことを必ずしも信頼できるわけではありません。
先のとがった

28

これ~ビットごとのNOT演算子で~xとほぼ同じ-(x+1)です。理解しやすいですね。そう:

~2;    // -(2+1) ==> -3

考えてください-(x+1)-1その操作を実行してを生成できます0

言い換えると、~数値の範囲で使用すると、入力値に対してのみ偽の(falseからに強制される0)値が生成され-1ます。それ以外の場合は、他の真の値が生成されます。

ご存知のように、-1は一般的にセンチネル値と呼ばれます。それは返す多くの機能のために使用される>= 0の値を成功し、-1ために失敗 C言語インチ indexOf()JavaScriptの戻り値の同じルール。

この方法で別の文字列内の部分文字列の有無をチェックすることは一般的です

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}

ただし、~以下のように実行する方が簡単です。

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}

あなたはJSを知りません:カイル・シンプソンによるタイプと文法


1
それはだ間違いなく人はそれを動作させた背景を理解していない場合であっても、額面で理解しやすいです。-(x+1)ifステートメントで見た場合、もう一度見てみましょう。チルダは、Javascriptの0ベースの性質を補うために何をしているのかを正確に教えてくれます。また、括弧が少ないほど読みやすくなります
通常のJoe

最初のチェックコードブロックでif (a.indexOf("Ba") > -1) {// found} //trueは、チルドの例より少し長いものの、入力した数を少なくすることができます。チルドの例は、2つの例よりもかなり少なく、新しいプログラマにとってはvar opinion = !~-1 ? 'more' : 'less'わかりやすいでしょう。
HalfMens

24

~indexOf(item) かなり頻繁に出てきて、ここでの答えは素晴らしいですが、たぶんそれを使う方法を知り、理論を「スキップ」する必要がある人もいるでしょう。

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }

1
私は同意します。Airbnb JavaScriptスタイルガイドは許可++--ず、「過度のトリッキーを奨励する」ため、何とか~生き残った(影に潜んでいる)github.com/airbnb/javascript/issues/540
Shanimal

@Shanimal代替があるlist.indexOf(item) >= 0か、... > -1Javascriptをゼロベースであり、最初からこの問題に対処することを選択しなかったので。さらに、意見(Airbnbのものと同じ)だけでも、JavaScriptで意味のあることをしている人なら誰でも知っており++--あまり一般的ではありませんが、その意味を推測できます。
定期的なジョー

@RegularJoe私はそのほとんどに同意します。私は個人的には必要++ありませんでした--が、しばらくの間mapforEachなどのプリミティブメソッドが原因で~使用されています。私の基準は、使用される標準にインクリメントおよびデクリメント演算子が含まれている場合に、過度にトリッキーだと見なされなかった理由についてです。CIS101が意味をなさないように何かを禁止すること。
Shanimal

11

ティルダトリックを使用してindexOf結果から真の値を作成することを検討している場合、代わりにincludesonメソッドをString使用するがより明示的であり、魔法が少なくなります。

'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false

これはES 2015の新しい標準メソッドであるため、古いブラウザでは機能しないことに注意してください。それが重要な場合は、String.prototype.includes polyfillの使用を検討してください

この機能は、同じ構文を使用する配列でも使用できます

['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false

古いブラウザのサポートが必要な場合のArray.prototype.includes polyfill次のとおりです。


2
include()の使用は避けてください。:これは、書き込み時にIE(だけでなく、古いブラウザ)のいずれかのバージョンでサポートされていません developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
Onshop

8
あなたは明確なコードを書くことができるようにそれとも...代わりにそこに最悪の共通分母JSインタプリタに応じて言語を書き込むので、コンパイラを使用する
カイル・ベーカー

2
@Benは正しいです。Netscape4.72でも機能しません。
mikemaccana 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.