【JavaScript】 let とは? const と var との違いも解説 <現役の一流エンジニアが教える>

JavaScript_image トップへ

はじめに

JavaScriptは、フロントエンジニアには欠かせない言語のひとつです。
また、フルスタックエンジニアを目指す上でも必須の言語といえるでしょう。

この記事では、JavaScriptの変数宣言で使用される「let」「const」「var」について分かりやすく解説します。
それぞれの違い、特徴、そして適切な使い方を学ぶことで、あなたはプログラミングの基礎を固めることができます。

私は多くの現場を経験してきましたが、「なんとなく let を使用しているけど、var との違いを説明できない」というエンジニアを多く見てきました。
もしまだ違いや特徴をなんとなくで理解している場合は、この機会にしっかり学習していきましょう!

結論

最初に、使い方について一覧表でまとめます。

項目名 説明
let 変数 を宣言したい時に使用します。
const 定数 を宣言したい時に使用します。
var 特別な理由がない限り、使用しないでください。

他の記事で、長々と文字ばかりで結局のところ何なのかよく分からないと感じた方も多いのではないでしょうか。
そこで、当記事では先に結論から一覧でまとめました。

この一覧表が全てで、以降はしっかり学びたい方向けに詳しく記載します。
具体的にコードを記述して説明しています。
必要な部分を飛ばし飛ばしでキャッチアップしてもらえたらと思います。
(心の声:本当は飛ばさずに全部読んでほしい…)

var

上の一覧表で記載した通り、特別な理由がない限りは使用しないでください。

昔は let と const という宣言方法が存在せず、var しかありませんでした。
そのため古いコードベースで改修を行っている現場だと、全て var で宣言されています。

昔は var だけでコーディングしていて、プログラムも問題なく動いていたなら var を使ってもいいじゃないか!
と考える方もいるかと思います。

しかしながら、var だと困ったことが起きてしまいます。
それが下記の2つです。

スコープ

var は関数スコープです。
分かりやすく言い換えると、関数ブロック以外のブロック内で変数宣言をした場合、ブロック外からでも変数にアクセスできてしまいます。
※ ブロック = 波括弧{ }
下記のコードをご覧ください。

< 例1 > 関数ブロック内の var で宣言した変数に、ブロック外からアクセス
      → エラー

function helloWorld() {
    var inBlockString = 'Hello World!';
}

// ブロック外から変数にアクセス
console.log(inBlockString);
// 出力結果:Uncaught ReferenceError: inBlockString is not defined at <anonymous>:6:13

< 例2 > 関数以外のブロック内の var で宣言した変数に、ブロック外からアクセス
      → アクセスできる

if (true) {
    var inBlockString = 'ブロックの中で変数宣言したよ!';
}

// ブロック外から変数にアクセス
console.log(inBlockString);
// 出力結果:ブロックの中で変数宣言したよ!

通常、ブロック内で変数宣言をする場合はそのブロック内で変数を使用することを想定します。
そのためブロック外からアクセスできてしまうと、意図しない挙動になってしまう恐れがあります。

再宣言

var の場合は、既に宣言済みの変数名と同じ名前で変数宣言ができてしまいます。
この場合は、宣言済みの変数が上書きされる形になります。

これにより、既に存在するとも知らずに変数を宣言して、想定外の値になってしまう恐れがあります。
特に複数人で同じソースファイルを改修する場合は、各メンバが同じ変数名を宣言して、それぞれ違う用途で使用してしまう可能性があります。

もし再宣言が不可でエラーになれば、コーディングの時点でこのような事態を防ぐことができます。

その他

他にも var で宣言するとグローバル変数に追加される、ホイスティングされるなどの違いがありますが、上記の「スコープ」と「再宣言」を理解できていれば大丈夫です!

let

変数を宣言する時に使用します。

ES6(ES2015)から追加された変数宣言の方法です。
ES6 とは JavaScript のバージョンを表し、現在では ES1 ~ ES15(別名:ES2024)まであります。

上述した var の問題点を解決するために登場しました。
そのため、主な var との違いは下記の2つです。

スコープ

let はブロックスコープです。
分かりやすく言い換えると、ブロック内で変数宣言をした場合、ブロック外から変数にアクセスすることができません!

下記のコードをご覧ください。

< 例1 > 関数ブロック内の let で宣言した変数に、ブロック外からアクセス
      → エラー

function helloWorld() {
    let inBlockString = 'Hello World!';
}

// ブロック外から変数にアクセス
console.log(inBlockString);
// 出力結果:Uncaught ReferenceError: inBlockString is not defined at <anonymous>:6:13

< 例2 > 関数以外のブロック内の let で宣言した変数に、ブロック外からアクセス
      → エラー

if (true) {
    let inBlockString = 'ブロックの中で変数宣言したよ!';
}

// ブロック外から変数にアクセス
console.log(inBlockString);
// 出力結果:Uncaught ReferenceError: inBlockString is not defined at <anonymous>:6:13

var の時と異なり、関数ブロック以外のブロックであっても、ブロック外からのアクセスがエラーになります。
これにより、意図しない挙動になることを防ぐことができます!

再宣言

let では、同名の変数を再宣言することができません。
これにより、意図せずに同じ変数名を宣言してしまうことを防げます。

< 例1 > 既存コードに変数名「hero」があることを知らずに、var でコード追加してしまった場合

// Aさんの既存コード
var hero = 'アンパンマン';
// (任意の処理)

// Bさんがプログラム改修でウルトラマンのコードを追加
var hero = 'ウルトラマン';
// (任意の処理)

// Aさんの既存コード
console.log(`${hero}は君さ~♪ 元気をだ~して♪`)
// 出力結果:ウルトラマンは君さ~♪ 元気をだ~して♪
// 想定していた出力は「アンパンマンは君さ~♪ 元気をだ~して♪」
// エラーにならず、実際にプログラムを稼働して初めて気づくことができます

< 例2 > 既存コードに変数名「hero」があることを知らずに、let でコード追加した場合

// Aさんの既存コード
let hero = 'アンパンマン';
// (任意の処理)

// Bさんがプログラム改修でウルトラマンのコードを追加
let hero = 'ウルトラマン';
// Uncaught SyntaxError: Identifier 'hero' has already been declared
// ここでエラーになるので、Bさんは既に変数名「hero」が存在していたことに気づくことができる
// (任意の処理)

// Aさんの既存コード
console.log(`${hero}は君さ~♪ 元気をだ~して♪`)

このように let で変数宣言をしていれば、意図せず再宣言してしまった場合に気づくことができます!

const

定数を宣言する時に使用します。

let と同じく、ES6(ES2015)から追加された変数宣言の方法です。
let と同じブロックスコープのため、ブロック外からアクセスすることはできません。

代入禁止

const は let と同じく再宣言が禁止です。
それにプラスして、代入も禁止になります。

< 例1 > 再宣言

// letと同じく、再宣言をするとエラーになります
// エラー内容:Uncaught SyntaxError: Identifier 'BIRTH_YEAR' has already been declared

const BIRTH_YEAR = 1999;
const BIRTH_YEAR = 2000;

< 例2 > 代入

// letと異なり、代入することもできなくなります
// エラー内容:Uncaught TypeError: Assignment to constant variable. at <anonymous>:2:12

const BIRTH_YEAR = 1999;
BIRTH_YEAR = 1234;

上記の例の通り、再宣言と代入では出力されるエラーの内容が異なります。

さいごに

いかがだったでしょうか。

ここまで読んだあなたは、var / let / const の違いを説明できるようになったと思います!
一流のエンジニアを目指す上では、基礎がとても重要です。

基礎が無くても、なんとなく動くものを作ることはできます。
しかしながら、それでは保守運用性が低く、機能追加や改修をする際に余計な工数やエラーが発生します。

また、今ではCopilotを活用してコーディングすることが主流になっていますが、AIが作ったコードが正しいかを判断する上でも、基礎が必要になってきます。

是非とも、最後まで読んでくださった読者様には一流のエンジニアになって多くの価値を提供し、たくさん稼げるようになって欲しいです!

コメント