脱・レガシー:現代のJavaScriptにおける変数宣言の「正解」とその理由
フロントエンドの現場でコードレビューをしていると、未だに「とりあえず `var` で書いて、必要なら `let` に直せばいいや」という若手に出会うことがある。
正直に言おう。その思考は、今すぐゴミ箱に捨ててくれ。
我々がコードを書く目的は「動くものを作ること」だけじゃない。「未来の自分やチームメンバーが、安心して読み解けるコードを残すこと」だ。JavaScriptという、良くも悪くも自由すぎる言語で、バグを未然に防ぐための最強の武器。それが変数宣言のルールだ。
今日は、なぜ現代のJSで `const` が王様なのか、その裏側にある技術的背景と現場の作法を叩き込む。
—
1. なぜ `var` は「禁忌」なのか?
`var` が抱える最大の問題は、その「スコープの広さ」と「巻き上げ(Hoisting)」にある。
`var` は関数スコープしか持たない。つまり、`if`文や`for`ループの中で宣言しても、その外側まで漏れ出す。これは現代のコンポーネント指向開発において、カプセル化を破壊するテロ行為に近い。
巻き上げという名の「裏切り」
以下のコードを見てほしい。
console.log(myVariable); // undefined と表示される(エラーにならないのが不気味だ)
var myVariable = “Hello, World!”;
JavaScriptエンジンは、コードを実行する前に「宣言」をスコープの先頭に持ち上げる。`var` は初期値が `undefined` で初期化されるため、宣言前にアクセスしてもエラーを吐かない。これがどれほど恐ろしいか分かるか? 数千行のファイルで、誰かが意図せず上書きした変数に、別の場所でアクセスしていても気づけないんだ。
—
2. const と let:現代の鉄則
ES6(ES2015)で導入された `const` と `let` は、ブロックスコープを持つ。`{ }` の外には漏れない。これだけでコードの安全性は劇的に向上する。
ベストプラクティスの黄金律
1. 基本は `const` を使う: 再代入の必要がないものはすべて `const` にする。
2. 再代入が必要な場合だけ `let` を使う: ループのカウンタなど、明らかに変化する値に限定する。
3. `var` は死んでも使わない: eslintのルールで強制的に警告を出す設定にしておくこと。
実践的なコード例
// 【推奨】変更しない値は必ず const
const API_ENDPOINT = “https://api.example.com/v1”;
// 【推奨】再代入が必要な場合だけ let
let retryCount = 0;
function fetchData() {
// ブロックスコープにより、この if 文の中だけで有効な変数が作れる
if (retryCount < 3) {
const status = "retrying"; // ここだけのスコープ
console.log(status);
retryCount++;
}
// console.log(status); // ここで呼び出すと ReferenceError: status is not defined となる
// これこそが「予期せぬ副作用」を防ぐための防御壁だ。
}
---
3. 「const は定数ではない」という誤解を解く
ここで一つ、中級者でも勘違いしやすいポイントがある。`const` で宣言したオブジェクトや配列の中身は変更できてしまうということだ。
「え、const なのに中身が変わるの?」と思うかもしれない。だが、`const` が保証しているのは「変数名(メモリ上の参照先)が固定されていること」であって、「中身のデータ構造の不変性」ではない。
const user = { name: “Alice” };
// OK: オブジェクトのプロパティ変更は可能
user.name = “Bob”;
// NG: 別のオブジェクトを代入しようとすると TypeError になる
// user = { name: “Charlie” };
これを防ぎたいなら、`Object.freeze()` を使うか、TypeScriptの `readonly` を活用する。実務では、単に `const` を使うだけでなく、データの不変性をどこまで担保すべきかを常に意識してほしい。
—
現場で使えるコーディング規約のヒント
チームで開発するなら、以下の指針を `eslint` や `prettier` と組み合わせて運用することをお勧めする。
- 宣言の順序: 依存関係がない限り、できるだけ使用する直前で宣言する(スコープを小さく保つため)。
- 初期化: 宣言と同時に値を代入する。`let x;` とだけ書いて、後で代入するコードはバグの温床だ。
- 名前付け: `const` を使うことで、「これは再代入されない」という意図が明確になる。コードを読む側は「この変数は最後までこのままなんだな」という安心感を持って読み進められる。
最後に
JavaScriptにおいて「どの変数宣言を使うか」は、単なる好みの問題じゃない。コードの意図をコンパイラや他の開発者に伝えるための「ドキュメンテーション」なんだ。
`const` でガチガチに縛り、本当に動的な部分だけを `let` で許容する。この厳格さが、大規模なフロントエンド開発を破綻させないための、我々シニアエンジニアの矜持だ。
まずは明日のプルリクエストから、`var` を撲滅し、`const` を愛することから始めてみてくれ。それが、君がプロフェッショナルとして一段階登るための第一歩だ。

コメント