この記事は翻訳作業中です。
let 文はブロックスコープの局所変数を宣言します。任意で値を代入して初期化できます。
構文
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
引数
var1,var2, …,varN- 変数の名前。任意の有効な識別子を指定できます。
value1,value2, …,valueN- 変数の初期値。任意の有効な式を指定できます。
説明
let を使用することで、変数のスコープをそれが使用されたブロック、文または式に限定することができます。これは var キーワードとは異なり、グローバル変数を定義したり、ブロックスコープに留まらない関数全体でのローカル変数を定義したりしません。
なぜ "let" という名前が選ばれたのかについては、こちら で解説されています。
スコーピングのルール
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
}
var とは異なり、プログラムのトップレベルと関数で、グローバルオブジェクト上にプロパティを生成しません。たとえば:
var x = 'global'; let y = 'global'; console.log(this.x); // "global" console.log(this.y); // undefined
内部関数でのクリーンなコード
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 のインスタンスを参照するため、意図したとおりに動作します。let を var で置き換えた場合、すべての内部関数は i の同じ最終値 6 を 返すため、意図したとおりに動作しないことに注意してください。また、我々は、各ループのスコープに新しい要素を生成するコードを移動することによって、ループ周りのスコープをクリーンに保つことができます。
プライベートインターフェースのエミュレート
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 を囲んで作られる暗黙のブロックがあります。
仕様
| 仕様 | ステータス | コメント |
|---|---|---|
| ECMAScript 2015 (6th Edition, ECMA-262) Let and Const Declarations の定義 |
標準 | 初期定義。let 式や let ブロックは定義されていない。 |
| ECMAScript Latest Draft (ECMA-262) Let and Const Declarations の定義 |
ドラフト |
ブラウザー互換性
| デスクトップ | モバイル | サーバー | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
let | Chrome
完全対応
49
| Edge 完全対応 12 | Firefox
完全対応
44
| IE 完全対応 11 | Opera 完全対応 17 | Safari 完全対応 10 | WebView Android
完全対応
49
| Chrome Android
完全対応
49
| Edge Mobile 完全対応 12 | Firefox Android
完全対応
44
| Opera Android 完全対応 17 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 4.0 | nodejs 完全対応 6.0.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 でトラックされています。