---
type: why
language: javascript
slug: strict-equality
title: "なぜ == ではなく === を使うのか"
title_tag: "なぜ === を使うのか — == が推移しない具体例で見る"
summary: >
  == は型を揃えてから比べるため、0 == '' が true になるなど直感と外れます。
  推移律が成り立たない具体例、== を使ってよい唯一の場面、Object.is との違いを確かめます。
description: >
  0 と空文字は等しいのに、空文字と '0' は等しくない。== は「等しい」が繋がりません。使ってよい唯一の場面と、=== でも足りない2つの例外まで実行して示します。
status: published
difficulty: 2
minutes: 8

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

sources:
  - title: "IsLooselyEqual — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-islooselyequal"
  - title: "IsStrictlyEqual — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-isstrictlyequal"
  - title: "Object.is — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-object.is"

terms: [厳密等価, 型変換, 推移律, SameValue]

links:
  related:
    - javascript/why/nan-equality
    - javascript/how-to/string/to-number
    - javascript/reference/collection/map-set
    - javascript/why/typeof-null

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

**`==` は比べる前に[key:型を揃えます]。その変換の規則が、覚えきれないほど複雑だからです。**

`===` は型が違えば即座に `false` です。規則は[num:1]つしかありません。

```js run
console.log(0 == '');
console.log(0 === '');
```
```output
true
false
```

## 覚えられない、という証明

規則を覚えようとするより、**覚える価値が無いことを見たほうが早い**です。

```js run
console.log(0 == '');
console.log('' == '0');
console.log(0 == '0');
```
```output
true
false
true
```

`0` と `''` は等しい。`''` と `'0'` は等しくない。なのに `0` と `'0'` は等しい。

**`a == b` かつ `b == c` なのに `a == c` とは限らない**、ではありません。
ここではもっと悪くて、[bad:「等しい」が繋がりません]。

数学の等号なら、`a = b` と `b ≠ c` なら `a ≠ c` のはずです。
`==` はそれを満たしません（[type:推移律]が成り立たない）。

**繋がらない規則は、頭の中で使えません。**

## 直感から外れる組み合わせ

```js run
console.log(0 == false);
console.log('0' == false);
console.log([] == false);
console.log([] == '');
console.log([1, 2] == '1,2');
```
```output
true
true
true
true
true
```

配列と文字列が等しくなります。**配列が文字列に変換されてから比べられる**からです。

`===` なら全部 `false` です。

```js run
console.log(0 === false);
console.log([] === false);
console.log([1, 2] === '1,2');
```
```output
false
false
false
```

## `==` を使ってよい唯一の場面

**`null` と `undefined` をまとめて判定するときだけ**です。

```js run
console.log(null == undefined);
console.log(null === undefined);
```
```output
true
false
```

`null` は `undefined` とだけ等しく、[em:他の何とも等しくなりません]。

```js run
console.log(null == 0);
console.log(null == false);
console.log(null == '');
```
```output
false
false
false
```

だから `v == null` は「[key:`null` か `undefined` のどちらか]」を、正確に表します。

```js run
function orDefault(value) {
  return value == null ? '無い' : value;
}

console.log(orDefault(null), orDefault(undefined));
console.log(orDefault(0), orDefault(''), orDefault(false));
```
```output
無い 無い
0  false
```

**`0` も空文字も `false` も、そのまま通っています。**
[dim:2つ目の出力で `0` と `false` のあいだが空いているのは、空文字が出ているためです。]

`!value` で書くと、こうはなりません。

```js run
function wrong(value) {
  return !value ? '無い' : value;
}

console.log(wrong(0), wrong(''), wrong(false));
```
```output
無い 無い 無い
```

[bad:意味のある `0` まで「無い」にされます]。

> **`??` があるならそちらを使ってください。**
> `value ?? '無い'` は `null` と `undefined` のときだけ右を返します。
> `== null` と同じ判定を、より短く書けます。

## `===` でも足りないとき

`===` にも[num:2]つだけ、直感と違うところがあります。

```js run
console.log(NaN === NaN);
console.log(0 === -0);
```
```output
false
true
```

`Object.is()` はこの2つを直します。

```js run
console.log(Object.is(NaN, NaN));
console.log(Object.is(0, -0));
```
```output
true
false
```

| 比べ方 | `NaN` と `NaN` | `0` と `-0` | 型変換 |
|---|---|---|---|
| `==` | `false` | `true` | **する** |
| `===` | `false` | `true` | しない |
| `Object.is()` | **`true`** | **`false`** | しない |
| `Set` / `includes` | `true` | `true` | しない |

`NaN` の話は別ページで詳しく扱っています。
→ [なぜ NaN === NaN は false なのか](/ja/javascript/why/nan-equality/)

## よくある誤解

### 「`==` のほうが便利」

型を揃えてくれるのは便利に見えます。**ですが、揃え方をこちらで選べません。**

```js run
const input = '10';

console.log(input == 10);
console.log(Number(input) === 10);
```
```output
true
true
```

結果は同じでも、下は[key:何をしているか読めば分かります]。
上は「`==` の規則がたまたまそう動いた」だけです。

**変換したいなら、自分で変換してください。**
→ [文字列を数値に変換する](/ja/javascript/how-to/string/to-number/)

### 「`===` は遅い」

そうではありません。`===` は型が違えばそこで終わります。
`==` のほうが[em:変換の手順を踏む]ぶん、やることが多くなります。

### 「文字列と数値を比べたいときは `==` が要る」

要りません。**どちらかに揃えてから `===` で比べます。**

```js run
const input = '10';

console.log(Number(input) === 10);
console.log(input === String(10));
```
```output
true
true
```

## 自分で確かめる

上のコードは書き換えて実行できます。

1. `0 == '\n'` を試す（空白だけの文字列はどうなるか）
2. `[] == ![]` を試す（両辺が変換される）
3. `null >= 0` と `null == 0` を並べて試す（比較と等価で規則が違う）

**予想してから実行してください。** 当たらないはずです。

## まとめ

- `==` は比べる前に[key:型を揃える]。その規則が複雑すぎる
- `0 == ''` と `0 == '0'` が真で `'' == '0'` は偽。**「等しい」が繋がらない**
- 使ってよいのは `v == null` だけ。**`null` と `undefined` をまとめて見る**
- ただし `??` が使えるならそちらが短い
- `===` でも `NaN` と `-0` は例外。**厳密に見るなら `Object.is()`**
- 型を揃えたいなら、`==` に任せず[em:自分で変換する]
