こんにちは!フロントエンドからNode.jsの深層まで、日夜JavaScriptと向き合っているシニアアーキテクトです。
今回は、JavaScriptの歴史と進化において極めて重要な役割を持つ「厳格モード(`use strict`)」、そしてそれが変数の宣言とスコープに与える強制力についてお話ししていきますね。
他のプログラミング言語(JavaやC#、Pythonなど)からやってきた開発者が、最初にJavaScriptで「おや?」とつまずくポイントの一つが、変数を宣言しなくても値が代入できてしまうという緩さです。実はこの「緩さ」、JavaScriptの黎明期における最大の設計ミスの一つと言われています。
ここをクリアすれば、あなたの書くコードは一気に堅牢になり、予期せぬバグとは無縁のプロフェッショナルなものになりますよ。さあ、一緒に本質をマスターしていきましょう!
—
1. そもそも「厳格モード(use strict)」とは何か?
JavaScriptは1995年の誕生以来、非常に短い期間で作り上げられたため、言語仕様の中に「少し危なっかしい挙動」がいくつか残されていました。その互換性を保ちつつ、モダンで安全なコードを書くための安全装置として、ES5(ECMAScript 5)で導入されたのが `use strict`(厳格モード) です。
これを発動させると、JavaScriptエンジン(V8など)は、あいまいな書き方や、バグの温床になりやすいコードに対して容赦なくエラーを投げるようになります。
使い方
使い方は驚くほどシンプルです。スクリプトの先頭、あるいは関数の先頭に文字列として記述するだけです。
‘use strict’; // ここで厳格モードを有効化
// この下では厳格なルールが適用されます
モダンな開発環境やモジュール(ES Modules)環境、あるいはTypeScriptなどのaltJSを使っている場合、これらはデフォルトで厳格モードとして動作します。しかし、その「裏側で何が起きているのか」を理解しておくことが、真に優れたエンジニアへの第一歩です。
—
2. 暗黙のグローバル変数という「魔物」
厳格モードがない世界( sloppy mode / 通常モード )で、初心者が最もやりがちな過ちを見てみましょう。
// 【通常モードの世界】
function calculateTotal() {
// let や const などの宣言キーワードを忘れてしまった!
totalScore = 100;
return totalScore;
}
calculateTotal();
console.log(totalScore); // 100 と表示されてしまう…!
あれ? `totalScore` なんて変数、どこでも宣言していませんよね? なぜエラーにならずに動いてしまうのでしょうか?
ここにJavaScriptの闇があります。通常モードにおいて、宣言されていない変数に値を代入しようとすると、JavaScriptエンジンは自動的にグローバルオブジェクト(ブラウザなら `window`、Node.jsなら `global`)のプロパティとしてその変数を勝手に生み出してしまいます。
これを「暗黙のグローバル変数(Implicit Global)」と呼びます。
なぜこれが最悪のバグを生むのか?
小さなスクリプトならまだしも、何万行もある巨大なアプリケーションではどうなるでしょう?
1. 開発者がうっかり変数名のスペルミスをする(例: `userCount` を `usreCount` と書く)。
2. 通常モードではエラーにならず、グローバル空間に新しい変数が勝手に誕生する。
3. 別のファイルで偶然同じ名前の変数を使っていた場合、データが上書きされ、原因の特定が極めて困難な破壊的バグ(副作用)を引き起こす。
V8エンジンのメモリ空間(ヒープ領域)の観点からも、意図しないグローバル変数はガベージコレクションの対象になりにくく、メモリリークの原因にもなり得ます。
—
3. 厳格モード(use strict)による強制力
ここで、今回の主役である `use strict` を登場させましょう。同じコードを厳格モード下で実行すると、V8エンジンはまったく異なる挙動を示します。
‘use strict’;
function calculateTotalStrict() {
// 宣言なしの変数代入
totalScore = 100; // 💥 ここで即座にエラー発生!
return totalScore;
}
calculateTotalStrict();
// 実行結果(エラー):
// ReferenceError: totalScore is not defined
素晴らしいですね! `ReferenceError`(参照エラー)という形で、JavaScriptエンジンがコードのミスをその場で即座に検知し、教えてくれます。
「エラーが出るなんて怖い」と思うかもしれませんが、開発者にとって「実行時や本番環境でサイレントに壊れること」が一番の恐怖です。ビルド時やテスト時にエラーとして即座に教えてくれる厳格モードは、私たちを守ってくれる最強の盾なのです。
—
4. 変数宣言以外における厳格モードの強力な恩恵
厳格モードの強制力は、変数宣言のミスを防ぐだけにとどまりません。モダンな開発において必須とされる理由が他にもいくつかあります。
① 予約語の保護
将来のECMAScriptの仕様追加のために予約されている言葉(`implements`, `interface`, `let`, `package`, `private`, `protected`, `public`, `static`, `yield` など)を変数名や関数名として使うことを禁止します。これにより、将来のアップデートへの移行がスムーズになります。
② 削除できないプロパティの削除禁止
通常モードでは、削除してはいけないオブジェクトのプロパティ(例:`Object.prototype` のプロパティなど)を `delete` しようとしても、サイレントに失敗するか、何も起きませんでした。厳格モードでは、これも `TypeError` として検知されます。
‘use strict’;
const obj = {};
Object.defineProperty(obj, ‘x’, { value: 42, writable: false });
// 読み取り専用プロパティを書き換えようとする
obj.x = 99; // 💥 TypeError: Cannot assign to read only property ‘x’ of object…
V8エンジンの最適化機構は、こうした不変性(Immutability)の保証を利用してコードを高速に実行するため、厳格モードはパフォーマンスの観点からも非常に理にかなっています。
—
まとめ:現代の開発におけるベストプラクティス
ここまでの話をまとめましょう。
1. 暗黙のグローバル変数は百害あって一利なし。 予期せぬバグやメモリ汚染の元凶となる。
2. `use strict` を使うことで、宣言漏れを即座にエラーとして検知できる。
3. 現代のJavaScript開発(ES Modules、TypeScript、Babel、React、Vue、Node.jsなど)では、自動的に、あるいは標準で厳格モードが有効になっている。
「変数を使うときは必ず `let` や `const` で宣言する」
この当たり前のようで最も大切な習慣を、技術とシステムの両面から強制・サポートしてくれるのが厳格モードです。
基本をしっかり押さえたあなたなら、もう変数やスコープ周りで迷うことはありません。自信を持って、クリーンでモダンなJavaScriptコードを書き進めていきましょう!