1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptの罠まとめ

― Date の月が +1 される問題から学ぶ ―

JavaScript には、知らないと普通に事故る仕様がいくつもあります。
歴史的な事情や後方互換の結果なので仕方ない部分もありますが、
実務では「ハマる前に知っておきたい」ものばかりです。

この記事では、実務で一度は踏む罠を中心に、
短いコード例付きでまとめました。


1. Date の月 (month) が 0 始まり問題

JavaScript の Date コンストラクタは、**月だけ 0 始まり(0〜11)**です。

const d = new Date(2025, 0, 10); // 2025年01月10日
console.log(d.getMonth()); // 0

これを知らずに「1月だから 1 を入れよう」とすると……

const d = new Date(2025, 1, 10);
console.log(d); // 2025-02-10T...

2月になります。
(1 → February)

対策

  • 日付ライブラリを使う
    • dayjs, date-fns, luxon
  • Date を使うなら、月を -1 する関数を用意する必要があります

2. new Date("YYYY-MM-DD") は UTC 扱いになる

一見ローカル日付に見えますが、
ISO形式の文字列は必ず UTC として解釈されます。

console.log(new Date("2025-01-01"));
// → 2024-12-31T15:00:00.000Z(日本では前日の深夜)

対策

ローカル日付として扱いたい場合は / 区切りを使う。

new Date("2025/01/01"); // ローカル日付として解釈

3. 0.1 + 0.2 !== 0.3

JavaScript の numberIEEE754 の倍精度浮動小数です。
そのため、完全に正確な小数計算はできません。

0.1 + 0.2 === 0.3; // false

対策

  • Math.round() などで桁を丸める
  • 金額計算などは decimal.js / big.js を使う

4. typeof null === "object"

有名な 歴史的バグです。

typeof null; // "object"

typeof だけで判定すると、
null チェック漏れの原因になります。


5. "5" - 1 === 4 なのに "5" + 1 === "51"

原因は **暗黙的な型変換(coercion)**です。

"5" - 1; // 4
"5" + 1; // "51"

対策

  • 数値化は必ず明示的に行う
Number(value);
  • "use strict" + TypeScript の導入

6. [] == ![] が true になる

[] == ![]; // true

JavaScript の 抽象等価(==)はカオスです。
正直、挙動を追いかける価値はありません。


7. for...in は配列用ではない

for...inオブジェクト用です。

const arr = [10, 20, 30];
for (let i in arr) {
  console.log(i);
}

一見問題なさそうですが、

  • インデックス順が保証されない
  • prototype のキーも拾う可能性がある

対策

配列には以下を使います。

  • for...of
  • forEach
  • map

8. parseInt の罠(切り捨て & 基数問題)

parseInt("10px"); // 10
parseInt("010");  // 古い環境では 8進数扱いの可能性

対策

必ず基数を指定する。

parseInt("010", 10);

9. == は使うな。基本すべて ===

0 == "";   // true
0 == "0";  // true
"" == "0"; // false

== の挙動をすべて暗記している人だけ使っていい」

それくらい危険です。

対策

  • == を使わない
  • ESLint で禁止する

10. 配列の「穴」は mapforEach でスキップされる

const arr = [1, , 3];
arr.map(x => x); // [1, , 3]

真ん中は実行されません。
地味ですが、デバッグがかなりつらいポイントです。


11. NaN は何とも等しくない

NaN === NaN; // false

対策

Number.isNaN(value);

12. マイナスゼロ (-0) が存在する

1 / -0; // -Infinity

表示上は区別できませんが、
内部的には 0-0 は別物です。


まとめ

JavaScript は、歴史的仕様と後方互換の影響で
直感に反する挙動が本当に多い言語です。

実務では、次のルールを守るだけでも事故はかなり減ります。

  • Date は基本そのまま使わず、日付ライブラリを使う
  • 暗黙の型変換に頼らない(=== を使う)
  • parseInt には必ず基数を指定
  • 配列に for...in を使わない
  • new Date("YYYY-MM-DD") を使わない

特に 「Date の月だけ 0 始まり」
全エンジニアが一度はやらかすポイントなので、
仕様として早めに身体に染み込ませておきたいところです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?