let 文はブロックスコープの局所変数を宣言します。任意で値を代入して初期化できます。

構文

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];

引数

var1, var2, …, varN
変数の名前。任意の有効な識別子を指定できます。
value1, value2, …, valueN
変数の初期値。任意の有効な式を指定できます。

説明

let を使用することで、変数のスコープをそれが使用されたブロック、文または式に限定することができます。これは var キーワードとは異なり、グローバル変数を定義したり、ブロックスコープに留まらない関数全体でのローカル変数を定義したりしません。

スコーピングのルール

let で定義された変数では、自身が定義されたブロックがスコープになります。そのブロックに含まれている全てのサブブロックでも同様です。この点において let のふるまいは var にとてもよく似ています。主に違うのは、 var で定義された変数のスコープはそれを含んでいる関数全体になるということです。次のコードはその例です。

function varTest() {
  var x = 31;
  if (true) {
    var x = 71;  // 同じ変数です!
    console.log(x);  // 71
  }
  console.log(x);  // 71
}

function letTest() {
  let x = 31;
  if (true) {
    let x = 71;  // 異なる変数
    console.log(x);  // 71
  }
  console.log(x);  // 31
}

内部関数でのクリーンなコード

let は、しばしば内部関数で使用されるとコードをクリーンにします。

var list = document.getElementById("list");

for (let i = 1; i <= 5; i++) {
  let item = document.createElement("li");
  item.appendChild(document.createTextNode("Item " + i));

  item.onclick = function (ev) {
    console.log("Item " + i + " is clicked.");
  };
  list.appendChild(item);
}

上述の例は、5 つの(匿名)内部関数のインスタンスが 5 つの異なる変数 i のインスタンスを参照するため、意図したとおりに動作します。letvar で置き換えた場合、すべての内部関数は i の同じ最終値  6 を 返すため、意図したとおりに動作しないことに注意してください。また、我々は、各ループのスコープに新しい要素を生成するコードを移動することによって、ループ周りのスコープをクリーンに保つことができます。

var とは異なり、プログラムのトップレベルと関数で、グローバルオブジェクト上にプロパティを生成しません。たとえば:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

プライベートインターフェースのエミュレート

constructor で処理することで、クロージャを使用することなくプライベートインターフェースを生成するために let ステートメントを使用できます:

var SomeConstructor;

{
    let privateScope = {};

    SomeConstructor = function SomeConstructor () {
        this.someProperty = "foo";
        privateScope.hiddenProperty = "bar";
    }

    SomeConstructor.prototype.showPublic = function () {
        console.log(this.someProperty); // foo
    }

    SomeConstructor.prototype.showPrivate = function () {
        console.log(privateScope.hiddenProperty); // bar
    }

}

var myInstance = new SomeConstructor();

myInstance.showPublic();
myInstance.showPrivate();

console.log(privateScope.hiddenProperty); // error

Temporal dead zone と let に関するエラー

同じ関数かブロックスコープで同じ変数を再宣言すると SyntaxError が発生します。

if (x) {
  let foo;
  let foo; // SyntaxError が投げられます。
}

ECMAScript 2015 では let は変数をブロックの先頭へ引き上げます。しかし、その変数を宣言より前で参照することは ReferenceError を引き起こします。ブロックの始めから変数宣言が実行されるまで、変数は "temporal dead zone" の中にいるのです。

function do_something() {
  console.log(foo); // ReferenceError
  let foo = 2;
}

switch 文には1つのブロックしかないため、エラーを発生させてしまうかもしれません。

switch (x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo; // 再宣言によって TypeError
    break;
}

関数に渡されるパラメータと同じ変数名で let を使用すると、for ループ内で undefined となります。

function go(n){
  for (let n of n.a) {
    console.log(n);
  }
}

go({a:[1,2,3]});

そのほかの例

ブロックの中で使うなら、 let の変数のスコープはそのブロックの中に制限されます。スコープが自身の宣言された関数全体になる var との違いに注意してください。

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // スコープはグローバル
  let b = 22; // スコープは if ブロック内

  console.log(a);  // 11
  console.log(b);  // 22
} 

console.log(a); // 11
console.log(b); // 2

標準的でない let 拡張

let ブロック

let ブロックは Gecko 44 からサポートされなくなっています (バグ 1167029) 。

let ブロックは、ブロックの外にある似た名前の変数の値に影響を与えずに、ブロックのスコープの中にある変数と値を関連づけるやり方を提供します。

構文

let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) block;

説明

let ブロックは変数に局所的なスコープをつけることを可能にします。コードブロックのレキシカルスコープに0個以上の変数を束縛するという動作をします。そのほかの点では、これはブロック文と全く同じです。let ブロックの中で var を使って宣言された変数のスコープは、依然として let ブロックの外で宣言されたのと同じだということに特に注意してください。そのような変数はやはり関数スコープを持ちます。 let ブロックを使うとき、 let に続く括弧は必須です。括弧を忘れると構文エラーが発生します。

var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

console.log(x + y); // 5

このコードブロックについての規則は JavaScript のほかのコードブロックと同じです。 let での変数宣言を使って、このブロック内のローカル変数を作ることができます。

スコープのルール

let を使って定義された変数のスコープは let ブロックそれ自体と、そこに含まれるほかのサブブロックですが、サブブロックで同名の変数が定義されているときを除きます。

let

let 式は Gecko 41 からサポートされなくなっています (バグ 1023609) 。

letは単一の式のみにスコープされた変数を作ることを可能にします。

構文

let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;

単一の式のみにスコープされた変数を作るために、 let が使えます。

var a = 5;
let(a = 6) console.log(a); // 6
console.log(a); // 5

スコープの規則

let 式があるとして:

let (decls) expr

expr を囲んで作られる暗黙のブロックがあります。

命名

"let" という名前がなぜ選ばれたかはこちらで確認できます。

仕様

仕様 ステータス コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Let and Const Declarations の定義
標準 初期定義。let 式や let ブロックは定義されていない。
ECMAScript 2017 Draft (ECMA-262)
Let and Const Declarations の定義
ドラフト  

ブラウザー互換性

機能 Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
基本サポート 41.0 12 44 (44) 11 17 ?
Temporal dead zone ? 12 35 (35) 11 ? ?
let 未サポート 未サポート 未サポート 未サポート 未サポート 未サポート
let ブロック 未サポート 未サポート 未サポート 未サポート 未サポート 未サポート
sloppy mode での許可 49.0 ? 44 (44) ? ? ?
機能 Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
基本サポート ? 41.0 44.0 (44) ? ? ? 41.0
Temporal dead zone ? ? 35.0 (35) ? ? ? ?
let 未サポート ? 未サポート 未サポート 未サポート 未サポート 未サポート
let ブロック 未サポート ? 未サポート 未サポート 未サポート 未サポート 未サポート
sloppy mode での許可 未サポート 49.0 44 (44) ? ? ? 49.0

Firefox 特有の注意

  • SpiderMonkey 46 (Firefox 46 / Thunderbird 46 / SeaMonkey 2.43) 以下では、再宣言すると SyntaxError の代わりに TypeError がスローされます バグ 1275240)。
  • SpiderMonkey 44 (Firefox 44 / Thunderbird 44 / SeaMonkey 2.41) 以下では、let<script type="application/javascript;version=1.7"> ブロック(またはより高いバージョン)にラップされた HTML のコードブロックでのみ使用可能であり、異なるセマンティックを持っていました。
  • Worker コード内でのサポートは、dom.workers.latestJSVersion フラグで隠されています (バグ 487070)。自由に let を使用できるバージョンから、このフラグは削除されます (バグ 1219523)。
  • SpIderMonkey での let の ES6 コンプライアンスは、バグ 950547 でトラックされています。

関連項目

ドキュメントのタグと貢献者

 このページの貢献者: YuichiNukiyama, Motchy, cohei, teoli, ethertank, Susisu, Wladimir_Palant, Potappo
 最終更新者: YuichiNukiyama,