TypeScript(および現代のJavaScript)では、変数をlet、const、varを使って宣言できますが、それぞれには重要な違いがあります。
例:
if (true) { let a = 10; const b = 20; var c = 30; } console.log(c); // 30 — ブロック外でも見える! console.log(a); // エラー: a is not defined console.log(b); // エラー: b is not defined
典型的なシナリオ:
const — 変更すべきでない値に使用(定数、設定、関数への参照)。let — 実行中に変更される値に使用(カウンタ、ループ内の変数)。var — 使用は推奨されず、古いコードのサポートのためのみ。constはオブジェクトを完全に変更不可能にできますか?説明し、例を示してください。
答え: いいえ、constは参照の変更を防ぐだけであり、オブジェクトのプロパティの変更からは保護されません!
const obj = { x: 1 }; obj.x = 2; // これは許可されます! obj = { x: 3 }; // エラー: 新しい参照を代入
完全な不変性を実現するためにはObject.freezeを使用します:
const frozen = Object.freeze({ x: 1 }); frozen.x = 2; // 厳密モードではエラーですが、必ずしもコンパイラが警告するわけではありません!
事例
大規模なフロントエンドプロジェクトをTypeScriptに移行する過程で、開発者はvarをletに置き換えたが、スコープがブロック単位であることを考慮しなかった。その結果、一部のforループのカウンタがループ外でアクセスできなくなり、論理に予期しないエラーが発生した:ループ終了後にループカウンタにアクセスしようとしたときにコードが動作しなくなった。
事例
開発者はconstを使用して設定オブジェクトを格納する定数を宣言し、プロパティが変更から保護されると考えた。後にランタイムでプログラムの別の場所がプロパティを変更し、外部コードがすべてのユーザーのグローバル設定を「予期せず」に変更したため、データ処理で捕らえにくいエラーが発生した。
事例
プロジェクト内でlet、const、およびvarが明確なポリシーなしに同時に使用されていた。一つのコンポーネントが関数内でvar変数を再宣言したが、別の場所ではその変数がletで宣言されていることを期待しており、そのためブロック外では見えなくなった。結果:変数のオーバーライド、内部ロジックの障害、不明瞭なライフサイクルに関する問題が複雑なデバッグを引き起こした。