web-dev-qa-db-ja.com

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

まず最初に、isNaN()Number.isNaN()がどのように機能するかを知っています。私はThe Definite Guideを読んでおり、David Flanaganが値がNaNであるかどうかを確認する方法の例を示しています。

x !== x

これは、truexである場合に限り、NaNになります。

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

x != x

同じように動作します。両方のバージョンを使用しても安全ですか、またはx !== xに対してtrueおよびx != xに対してfalseを返すJavaScriptの値がありませんか?

147
Giorgi Nakeuri

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

... am JavaScriptでx!== xに対してtrue、x!= xに対してfalseを返す値がありませんか?

いいえ、あなたは違います。 !==!=の唯一の違いは、必要に応じてオペランドの型を同じにするために後者が型強制を行うことです。 x != xでは、オペランドのタイプが同じであるため、x !== xとまったく同じです。

これは、 Abstract Equality Operation の定義の最初から明らかです。

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

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

  4. ...

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

したがって、NaNのみがx !== xに対してtrueを与えるというFlanaganが正しい場合、x != xに対してNaNのみがtrueを与えることも確かです。

多くのJavaScriptプログラマーは、デフォルトで===および!==を使用して、ルース演算子が行う型強制に関する落とし穴を回避しますが、この場合のFlanaganのstrict vs. loose演算子の使用について読むべきものはありません。

127
T.J. Crowder

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

ただし、多くのプログラマーは、JavaScriptで==または!=を避けています。たとえば、Douglas Crockfordは、JavaScript言語の「 bad parts 」とみなしています。なぜなら、これらは予期せぬ混乱した方法で動作するためです。

JavaScriptには、===!==、およびそれらの邪悪な双子==!=の2組の等価演算子があります。良いものはあなたが期待する方法で動作します。

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

37
jkdev

ただの楽しみのために、xNaNではなく、演算子の動作が異なる人工的な例を示します。最初に定義します:

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

それから

x != x // false

しかし

x !== x // true
22
GOTO 0

グローバルオブジェクトを使用せずにx !== xを生成するのは、NaNだけではありません。この振る舞いを引き起こす巧妙な方法はたくさんあります。ゲッターを使用するものは次のとおりです。

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

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

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

2

時々、画像は言葉よりも優れているので、これを確認してください table (これが私が答えをコメントにせずにいる理由は、視認性が向上するからです)。

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

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

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

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

明確ではありませんが、 ECMA を参照せずに、比較するときにJavaScriptが考慮し、コードが以下のように真と評価されるようにします。

 var howAmISupposedToKnowThat = [] == false; //true
0
MVCDS