---
type: why
language: javascript
slug: nan-equality
title: "なぜ NaN === NaN は false なのか"
title_tag: "なぜ NaN === NaN は false なのか — 3つの比べ方と判定法"
summary: >
  NaN は特定の値ではなく「数値として表せなかった」という印です。
  そのため === では等しくなりません。includes や Set では等しく扱われる理由も、実行して確かめられます。
description: >
  NaN は特定の値ではなく「数値として表せなかった」という印だからです。includes や Set では等しく扱われる理由、Object.is との違いまで実行して確かめられます。
status: published
difficulty: 3
minutes: 8

versions:
  verified: "Node 22.22.3"
  since: "ES1"
  deprecated: null
  removed: null

sources:
  - title: "IsStrictlyEqual — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-isstrictlyequal"
  - title: "SameValueZero — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-samevaluezero"
  - title: "Number.isNaN — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-number.isnan"
  - title: "IEEE 754-2019 — IEEE Standard for Floating-Point Arithmetic"
    url: "https://standards.ieee.org/ieee/754/6210/"

terms: [NaN, SameValueZero, SameValue, 厳密等価]

links:
  related:
    - javascript/how-to/array/remove-duplicates
    - javascript/why/float-precision
    - javascript/how-to/string/to-number
    - javascript/why/strict-equality

content_updated_at: 2026-09-07
published_at: 2026-09-07
---

`NaN` は[key:特定の値ではなく]、「数値として表せなかった」という印だからです。
[bad:計算が失敗した2つの結果が、同じ失敗だとは限りません]。
だから比べても等しくなりません。これは JavaScript ではなく [type:IEEE 754] が決めています。

```js run
console.log(NaN === NaN);
console.log(0 / 0 === Number('あ'));
```
```output
false
false
```

`0 / 0` と `Number('あ')` はどちらも `NaN` になりますが、[em:同じ失敗ではありません]。

## 仕様ではどう書かれているか

`===` の中身は [type:IsStrictlyEqual] という手続きです。
数値同士のときは [type:Number::equal] を呼び、そこにこう書いてあります。

> 引数のどちらかが `NaN` なら `false` を返す。

つまり[key:例外なく最初に落とされます]。大小比較も同じで、`NaN` が入ると全部 `false` になります。

```js run
console.log(NaN < 1);
console.log(NaN > 1);
console.log(NaN <= NaN);
```
```output
false
false
false
```

`<` と `>` と `<=` が[bad:全部 false]になります。「どちらでもない」が正しい答えなので、
[em:否定しても真になりません]。

## ところが includes や Set では等しく扱われる

同じ `NaN` なのに、結果が変わります。

```js run
const arr = [NaN];

console.log(arr.indexOf(NaN));
console.log(arr.includes(NaN));
console.log(new Set([NaN, NaN]).size);
console.log(Object.is(NaN, NaN));
```
```output
-1
true
1
true
```

**比べ方が3種類あるからです。**

| 比べ方 | 使っているところ | `NaN` と `NaN` | `+0` と `-0` |
|---|---|---|---|
| [type:IsStrictlyEqual]（`===`） | `===` / `indexOf` | [bad:false] | [em:true] |
| [type:SameValueZero] | `includes` / `Set` / `Map` | [em:true] | [em:true] |
| [type:SameValue] | `Object.is` | [em:true] | [bad:false] |

```js run
console.log(0 === -0);
console.log([0].includes(-0));
console.log(Object.is(0, -0));
```
```output
true
true
false
```

`NaN` と `-0` の[key:どちらを区別したいか]で、使う道具が変わります。

- 素直に比べたい … `===`
- 「その値が入っているか」を見たい … `includes` / `Set`（`NaN` も見つかる）
- `-0` まで見分けたい … `Object.is`

## 判定するには

`===` で判定できないので、専用の関数を使います。

```js run
console.log(Number.isNaN(NaN));
console.log(Number.isNaN(0 / 0));
console.log(Number.isNaN(1));
```
```output
true
true
false
```

### グローバルの isNaN() を使わない

名前がよく似ていますが[key:別物]です。`isNaN()` は[bad:先に数値へ変換します]。

```js bad
console.log(isNaN('あ'));
console.log(isNaN(undefined));
console.log(isNaN(''));
console.log(isNaN([]));
```
```output
true
true
false
false
```

`'あ'` は `NaN` ではありません。[bad:変換したら NaN になった]だけです。
`''` と `[]` が `false` なのも同じ理由で、どちらも `0` に変換されます。

**「これは NaN か」を知りたいなら `Number.isNaN()` を使ってください。**
`isNaN()` が答えているのは「これは数値に変換できないか」という別の質問です。

## よくある誤解

### typeof NaN は 'number' ではない、と思っている

`NaN` は[key:数値型の値]です。「数値ではない（Not a Number）」という名前ですが、型は数値です。

```js run
console.log(typeof NaN);
console.log(typeof (0 / 0));
console.log(Number.isFinite(NaN));
```
```output
number
number
false
```

型で弾くことはできません。値として判定する必要があります。

### 自分自身と等しくないことを利用する

`NaN` は[key:自分自身と等しくない唯一の値]です。この性質で判定する古い書き方があります。

```js run
const x = 0 / 0;
const y = 1;

console.log(x !== x);
console.log(y !== y);
```
```output
true
false
```

たしかに `NaN` のときだけ `true` になります。ですが読んだ人が[bad:意図を読み取れません]。
`Number.isNaN(x)` と書いてください。

## どこで NaN が生まれるか

意図せず `NaN` になる場面はだいたい決まっています。

```js run
console.log(Number('12px'));
console.log(parseInt('あ'));
console.log(undefined + 1);
console.log(Math.sqrt(-1));
console.log([1, 2].reduce((a, b) => a + b, undefined));
```
```output
NaN
NaN
NaN
NaN
NaN
```

数値に変換できない文字列、`undefined` との計算、定義域の外。
[key:入り口で弾く]のがいちばん確実です。
文字列を安全に数値へ直す手順は
[文字列を数値に変換する](/ja/javascript/how-to/string/to-number/) にまとめてあります。

同じ [type:IEEE 754] が決めている小数の誤差については
[なぜ 0.1 + 0.2 は 0.30000000000000004 になるのか](/ja/javascript/why/float-precision/) にあります。

配列から `NaN` を含む重複を消したいときの注意は
[配列から重複を取り除く](/ja/javascript/how-to/array/remove-duplicates/) にまとめてあります。
