(NaN!= NaN)と(NaN!== NaN)の違いは何ですか?


148

まず最初に、私は方法isNaN()Number.isNaN()作業を知っていることを述べたいと思います。私はデビッドフラナガンによる明確なガイドを読んでいて、値がNaN次の値であるかどうかを確認する方法の例を示しています

x !== x

これは、になりますtrue場合にのみxですNaN

しかし今、私は質問があります。なぜ彼は厳密な比較を使用するのですか?どうやら

x != x

同じように動作します。両方のバージョンを使用しても安全ですか、またはtruefor x !== xおよびfalseforで返されるJavaScriptの値が不足していますx != xか?


10
フラナガンは!==チェックよりも!=チェックを好むだけかもしれません。私が知っている限り、他に価値はありませんx != x。好む人:しかし、JavaScript開発者の2つのグループがある!=と好む人!==、それは等速、明瞭さ、表現力、のためのもの
スティーブ・クロスタース

30
厳密な比較が同じように動作するのに、なぜ緩い比較を使用するのですか?
Ry-

3
@Raulucco:NaN一意のタイプではなく、数値です。それはそれ自体とは異なるユニークなです。
TJクラウダー

8
タイトルは誤解を招くようです。「x!= xはx!== xと異なるのですか」のようなものに変更することをお勧めします。
TJクラウダー

6
@femmestem:Giorgiは「この場合」はスタイルの問題だと言った。そして彼はその点で正しい。それはないオペランドの型が異なる場合、スタイルが、それはある、彼らは同じだときのスタイル。別に:フラナガンは、これらの比較はWTHやっている===のNaNでポイントを作るためにはNaNが自分自身に等しくないと。彼は「間違っている」わけではなく、それが機能しないことを示すために、指導演習としてそれをやっています。
TJクラウダー

回答:


128

まず、これNaNは非常に特別な値であることを指摘しておきます。定義上、それ自体とは異なります。これは、JavaScriptの数値が使用されているIEEE-754標準に由来しています。「数字ではない」値は、ビットが完全に一致する場合でも、それ自体と等しくなることはありません。(これらは必ずしもIEEE-754にあるとは限りませんが、複数の異なる「非数」の値を許可します。)これが発生する理由です。JavaScriptの他のすべての値はそれ自体と等しく、NaN特別なものです。

... JavaScriptでx!== xに対してtrueを返し、x!= xに対してfalseを返す値が欠けていますか?

いいえ、そうではありません。唯一の違い!==とは!=同じになるようにオペランドの型を取得するために必要であれば、後者は型強制を行うということです。ではx != x、オペランドの型が同じであるため、とまったく同じx !== xです。

これは、抽象等値演算の定義の最初から明らかです。

  1. ReturnIfAbrupt(x)。
  2. ReturnIfAbrupt(y)。
  3. Type(x)がType(y)と同じ場合、

    厳密な等価比較x === yを実行した結果を返します。

  4. ...

最初の2つのステップは、基本的な配管です。したがって、実際には、最初のステップは==、型が同じかどうかを確認し、同じ場合は===代わりに行うことです。!=そしてそれ!==は単に否定されたバージョンです。

フラナガンが唯一という正しいのであればNaN当てはまり与えるだろうx !== x、我々はそれが唯一のも事実だことを確認することができますNaNのために真なりますx != x

使用に多くのJavaScriptプログラマーデフォルト===!==ゆるい事業者が行う型強制の周りにいくつかの落とし穴を避けるために、この場合では、厳密な対緩やかなオペレータのフラナガンの使用に読み込むためには何もありません。


4.9.1 - Equality and Inequality Operatorsセクションを読み直しましたが、これが答えのようです。===比較のポイントは次のとおり If the two values have the same type, test them for strict equality as described above. If they are strictly equal, they are equal. If they are not strictly equal, they are not equalです。
Giorgi Nakeuri

@GiorgiNakeuri:たぶん、フラナガンの本の4.9.1が何を指しているのかわかりませんか?しかし、それは基本的に上記の仕様の引用が言っていることを言っている、はい。
TJクラウダー

2
これが私の質問に形式化された正確な方法で答えるため、これを受け入れます。説明ありがとうございます!
Giorgi Nakeuri

1
@Moshe:「ライブバインディング」とはどういう意味ですか?(この用語は仕様に表示されていません。)GOTO 0の例のようにa実際には関数であり、同じ値を2回返さないという意味ですか?それは同じことではないのための!==OPがについて尋ねたものですこれは、本当でしょう。異なる値を返す関数にすぎません。呼び出しごとに異なる値を返す可能性があるfoo() !== foo()ため、必ずしもtrueである必要はありませんfoo
TJクラウダー

1
@Mosheさて、それはプロパティとゲッターをいじる非常に厄介な方法です。ただし、GOTO 0の例とほとんど同じように見えますが、間接層が追加されています。
JAB、2015

37

NaNでの目的のために、!=!==同じことを行います。

ただし、多くのプログラマーはJavaScriptを使用しない==!=、JavaScriptを使用しています。たとえば、Douglas Crockford は、JavaScript言語の「悪い部分」の1 つと見なしています。

JavaScriptは、等価演算子の二組を持っています===!==、それらの邪悪な双子==!=。良いものはあなたが期待するように働きます。

...私のアドバイスは、邪悪な双子を使用しないことです。代わりに、常にとを使用===してください!==


2
問題はNaNについてではありません(タイトルにもかかわらず)。問題は、「JavaScriptでx!== xの場合はtrueを返し、x!= xの場合はfalseを返す値が欠けているか」です。
TJクラウダー

@TJCrowder 2つの質問です。最初の質問は「両方のバージョンを使用しても安全ですか」であり、答えは両方のバージョンが同等であるということです。私はすべてを詳細に説明する「実際の」答えが好きです。
jkdev

22

ただ面白くするために、そうでxはないNaNがオペレーターがとにかく異なる動作をする人工的な例を紹介しましょう。最初に定義:

Object.defineProperty(
  self,
  'x',
  { get: function() { return self.y = self.y ? 0 : '0'; } }
);

次に、

x != x // false

だが

x !== x // true

9
ハ!:-)しかし、それfoo() != foo()はfooが1と2を返すところです。たとえば、は同じではなく、単に異なる値を比較しているだけです。
TJクラウダー

2

指摘したいのNaNx !== x、グローバルオブジェクトを使用せずに生成されるものだけではありません。この動作を引き起こす賢い方法はたくさんあります。これはゲッターを使用したものです:

var i = 0, obj = { get x() { return i++; }};
with(obj) // force dynamic context, this is evil. 
console.log(x === x); // false

他の答えが指摘するように、==型強制変換を実行しますが、他の言語と同様に、標準と同様に-NaNは計算の失敗を示し、正当な理由からそれ自体とは異なります。

私を超えた何らかの理由で人々はこれをJSの問題と思いますが、doubleを持つほとんどの言語(つまり、C、Java、C ++、C#、Pythonなど)はこの正確な動作を示し、人々はそれで問題ありません。


2
はい、それはまさに@TJCrowderがGOTO_0の回答へのコメントで述べたことですよね?
Giorgi Nakeuri

これらの他の言語であいまいな型強制を取得する方法を明確にできますか?
chicocvenancio 2015

0

時々、画像は言葉よりも良いので、この表をチェックしてください(コメントの代わりにこれを回答にしたのは、よりよく見えるためです)。

厳密な等価比較(===)は、タイプとコンテンツが一致する場合にのみtrueを返すことがわかります。

var f = "-1" === -1; //false

抽象等価比較(==)は、型を変換してから厳密にそれらを比較することにより、コンテンツ*のみをチェックします。

var t = "-1" == -1; //true

明確ではありませんが、ECMAに相談せずに、JavaScriptが比較する際に以下のコードがtrueと評価される方法で何を考慮するかはわかりません。

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