Babelの ES6へのガイド は言う:
let
は新しいvar
です。
明らかに、唯一の違いは、var
が現在の関数にスコープされるのに対し、let
は現在のblock。 この答え にいくつかの良い例があります。
ES6コードでvar
を使用する理由がわかりません。関数全体に特定の変数のスコープを設定する場合でも、let
で宣言を関数ブロックの先頭に配置することで、var
でこれを行うことができます。また、for
ブロックなどでより細かくスコープを設定する場合は、それも可能です。
したがって、私の本能は、ES6コードを記述するときにvar
の使用を完全に停止することです。
私の質問は、私はこれについて間違っていますか? var
よりもlet
の方が望ましい正当なケースはありますか?
Doug Crockfordはlet
について this point で彼の講演「 The Better Parts 」について議論しています。
重要なのは、let
は誤解の原因を回避することです、特に。ブロックスコープを持つ言語によって設定された期待を持つプログラマーのために。 var
にはブロックスコープのようにがのように見えますが、関数スコープ(関数全体で表示される変数を宣言します)があります。
var
は、機械で生成されたコードのような極端な場合でも役立つ可能性がありますが、私は懸命にストレッチしています。
(const
も新しく、ブロックスコープがあります。let x = {'hi': 'SE'}
以降はx
に再割り当てできますが、const y = x
以降はy
に再割り当てできません。何かが誤ってあなたの下から変わってしまうのを防ぐので、多くの場合それが望ましいです。しかし、明確にするために、フリーズしない限り、オブジェクトy.hi = 'SO'
を変更できます。)
実際には、ES6の印象は適切です:Adopt let
およびconst
。 var
の使用を停止します。
( "The Better Parts"の別のパフォーマンス では、修正するのではなく===
が追加された理由 ==
の問題 。==
は「驚くべき」結果を生成するため、===
を採用してください。)
明らかにする例
Mozilla Developer Network は、var
が意図したとおりに機能しない例を示しています。これらの例は、Webページでonclick
ハンドラーを設定する現実的な例です。これは小さなテストケースです:
var a = [];
(function () {
'use strict';
for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
a.Push( function() {return i;} );
}
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]
// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]
var
は、すべてのループ反復が同じ関数スコープのi
変数を共有するため、トリップします。ループが終了すると、値は5
になります。
別のわかりやすい例
function f(x) {
let y = 1;
if (x > 0) {
let y = 2; // `let` declares a variable in this block
}
return y;
}
[f(1), f(-1)] // --> [1, 1]
// Start over, but change `let` to `var`.
// --> [2, 1]
let
は、ブロックスコープの変数を宣言します。 var
は、関数全体で同じ変数を参照することで混乱させます。
正しいコードを記述している場合は、セマンティックを変更せずに、すべてのvar
ステートメントをlet
ステートメントに変換できるでしょう。
let
は、識別子が表示される範囲を縮小するため、推奨されます。これにより、初めて使用するサイトで変数を安全に宣言できます。
const
はlet
よりも望ましいです。参照を変更する必要がない限り、const
宣言を使用します。これには、let
のすべての利点に加えて、単一化された変数の存在を減らし、コードを一般的に推論しやすくします。参照を変更する必要があるかどうかわからない場合は、明示的に変更する必要があるまで、それをconst
と宣言してください。
私は必ずしもあなたが間違っているとは思いませんが、varの使用には注意事項があります。基本的に、let
は、開発者がJavaScriptの愚かさ、特に名前の競合を回避するのに役立つはずです。 var
はcloses関数のスコープに行きたいので、スコープが大きいようです。関数内のブロックのスコープ内で一時変数を使用できるようにする必要がある場合など、varが必要になる場合があります。そうでない場合は、varよりもlet
を優先すると、名前の競合が発生しやすくなります。簡単に言えば、ES6がlet
を導入した時期です。
Es6では「let」のみを使用することに同意する傾向があります。 AFIK、「let」を再宣言するとエラーが発生しますが(これは適切です)、「var」を使用すると、値をオーバーライドするだけです(es5の「strictモード」でも処理されます)。