スコープ
Scope
スコープは、変数などの名前を、プログラムのどこから参照できるかという範囲です。名前が見える範囲と、オブジェクトがメモリ上に存在する期間は同じではありません。
🐾 猫で例えると?
猫じゃらしが茶トラの視界に入らない場面を、その位置から名前が見えないことにたとえます。ただしJavaScriptのスコープは、実行中に猫が向きを変えるような視界ではなく、主にコードが記述された構造で決まります。
💻 プログラミングにおける「スコープ」とは?
プログラミングにおいて、変数はどこからでもアクセスできる方が便利に思えるかもしれません。しかし、実際の開発現場ではそれがバグの最大の温床になります。スコープは「このデータを使えるのは、この処理ブロックの中だけ」と明確に制限をかける機能です。
どこからでもアクセスできる「グローバル変数」を多用すると、思いがけない場所で値が上書きされ、システム全体の予測がつきにくくなります。スコープを適切に狭めることは、影響範囲を限定し、コードの保守性を高めるために不可欠です。
⚠️ スコープの仕組みと注意点
JavaScriptには関数・ブロック・モジュールなどのスコープがあります。letとconstはブロックの範囲を持ちますが、varは同じ規則ではありません。モジュールの先頭の変数も、別のモジュールから自動的に見えるグローバル変数にはなりません。
ブロックスコープによる変数の保護
意図しないスコープの広がりは、名前の衝突を引き起こします。特に複数人で開発を行う現場では、他のエンジニアが同じ変数名を使ってしまうリスクを避けるため、スコープは可能な限り小さく保つのが鉄則です。
const message = "外側";
function checkScope() {
const message = "関数の内側"; // 外側の同名の変数を隠す
console.log(message);
}
checkScope(); // 関数の内側
console.log(message); // 外側
if (true) {
const snack = "カリカリ";
}
// console.log(snack); // ブロックの外なのでReferenceError 関数が外側の変数を保持するクロージャーでは、関数の呼び出し終了後も値が必要になります。スコープを抜けた瞬間に必ずメモリが解放されるわけではありません。GCによる回収は、値が到達可能かどうかにも関係します。
🛠️ スコープを賢く使うためのポイント
現場でコードを書く際、予期せぬエラーを防ぎ、安全なシステムを構築するための重要なポイントです。
- 名前の範囲を必要な場所へ絞る: 使う場所の近くで宣言すると追いやすくなります。同名の変数で外側を隠すシャドーイングは便利な場合もありますが、取り違えが起きないか確認します。
- グローバル変数の使用を避ける: どこからでも書き換え可能な変数は、予期せぬバグや名前の衝突を引き起こす原因となるため極力使わない。
- 定数(const)を優先して使う: 再代入が不要な値は定数として宣言し、値が不用意に変更されるリスクをシステム的に排除する。
茶トラの視界に入る範囲のように、変数にも参照できる範囲があります。使う場所に近い狭いスコープで宣言し、同じ名前の変数が別の範囲にないかを見ると、意図しない変数を読んだり書き換えたりする原因を追いやすくなります。