JavaScript 速習チュートリアル

JavaScript let

1. JavaScript let の概要

let キーワードは、ES6 (2015) で導入されました。

  • let で宣言されたバリアブルはブロックスコープを持ちます。
  • let で宣言されたバリアブルは、使用する前にデクレア(宣言)する必要があります。
  • let で宣言されたバリアブルは、同じスコープ内で再宣言することができません。

2. ブロックスコープ (Block Scope)

ES6 (2015) より前、JavaScriptにはブロックスコープが存在しませんでした。
当時のJavaScriptには、グローバルスコープ関数スコープしかありませんでした。

ES6で導入された letconst という2つの新しいキーワードにより、JavaScriptにブロックスコープがもたらされました。

コード例{ } ブロック内で宣言されたバリアブルは、ブロックの外からアクセスすることはできません。

{
  let x = 2;
}
// ここで x は使用できません

3. 関数スコープ (Function Scope)

ファンクションの内部で宣言されたバリアブルは、varletconst のいずれであっても関数スコープを持ちます。

コード例

function myfunction() {
  var x = 1;   // 関数スコープ
  let y = 2;   // 関数スコープ
  const z = 3; // 関数スコープ
}
// ここで x は使用できません
// ここで y は使用できません
// ここで z は使用できません

4. グローバルスコープ (Global Scope)

var キーワードで宣言されたバリアブルは、常にグローバルスコープ、あるいは(関数内の場合は)関数スコープを持ちます。
var で宣言されたバリアブルは、ブロックスコープを持つことができません。

コード例{ } ブロック内で var を使用して宣言されたバリアブルは、ブロックの外からアクセス可能です。

{
  var x = 2;
}
// ここで x を使用できます

5. 再宣言の禁止 (Cannot be Redeclared)

let で定義されたバリアブル再宣言できません。
これにより、誤って既存のバリアブルを上書きしてしまうリスクを回避できます。

let では、以下のような記述は不可能です。

let x = "ジョン・ドウ";

let x = 0; // 構文エラーになります

対して、var で定義されたバリアブルは何度でも再宣言が可能です。

var x = "ジョン・ドウ";

var x = 0; // 許容されます

6. 変数の再宣言による影響 (Redeclaring Variables)

var キーワードを使用した再宣言は、しばしば問題を引き起こします。
ブロック内でバリアブル再宣言すると、ブロックの外にある同名のバリアブルまで上書きされてしまいます。

コード例(var の場合)

var x = 10;
// ここで x は 10

{
var x = 2;
// ここで x は 2
}

// ブロックの外でも x は 2 になってしまう

let キーワードを使用すれば、この問題を解決できます。
ブロック内でバリアブル再宣言しても、ブロック外のバリアブルには影響を与えません。

コード例(let の場合)

let x = 10;
// ここで x は 10

{
let x = 2;
// ここで x は 2
}

// ブロックの外では x は依然として 10

7. var, let, const の違い

特徴varletconst
ブロックスコープNoYesYes
再宣言YesNoNo
再代入(アサイン)YesYesNo
ホイスティングYesYes (※)Yes (※)
this へのバインドYesNoNo

letconstホイスティングされますが、初期化されないため、宣言前にアクセスするとエラーになります。

7.1 何が優れているのか?

  • letconst はブロックスコープを持ちます。
  • letconst は再宣言ができません。
  • letconst は使用前にデクレアする必要があります。
  • letconstthis にバインドされません。
  • letconst は(実質的に)ホイスティングされません。

7.2 何が問題か?

  • var は宣言しなくても使えてしまう場合があります(古い挙動)。
  • var はホイスティングされます。
  • varthis にバインドされます。

8. ブラウザのサポート状況

let および const キーワードは、Internet Explorer 11 以前ではサポートされていません。
以下の表は、完全なサポートを開始した最初のブラウザバージョンを示しています。

Chrome 49Edge 12Firefox 36Safari 11Opera 36
2016年3月2015年7月2015年1月2017年9月2016年3月

9. スコープ別の再宣言ルール

var を使った再宣言は、プログラムのどこでも許可されます。

コード例

var x = 2;
// 現在 x は 2

var x = 3;
// 現在 x は 3

しかし、let を使用する場合、同じブロック内での再宣言は許可されません。

コード例

var x = 2;   // 許容される
let x = 3;   // 許可されない(エラー)

{
let x = 2;   // 許容される
let x = 3;   // 許可されない(エラー)
}

{
let x = 2;   // 許容される
var x = 3;   // 許可されない(エラー)
}

異なるブロック内であれば、let を使用して同名のバリアブルを宣言することは可能です。

コード例

let x = 2;   // 許容される

{
let x = 3;   // 許容される
}

{
let x = 4;   // 許容される
}

10. let とホイスティング (Let Hoisting)

var で定義されたバリアブルは、スコープの先頭にホイスティング(巻き上げ)され、いつでも初期化可能です。 つまり、デクレアする前にそのバリアブルを使用することができます。

コード例
以下のコードは正常に動作します。

carName = "ボルボ";
var carName;

ホイスティングについて詳しく知りたい場合は、「JavaScript Hoisting」の章を参照してください。

let で定義されたバリアブルもブロックの先頭にホイスティングされますが、初期化はされません。
そのため、let バリアブルを宣言前に使用しようとすると、ReferenceError(参照エラー)が発生します。

コード例

carName = "サーブ";
let carName = "ボルボ"; // ReferenceError が発生します