ES6で「var」キーワードを使用する理由はありますか?


261

ES6に対する Babelのガイドによると:

let新しいvarです。

明らかに唯一の違いは、現在のブロックにスコープされるのvarに対して、現在の関数letスコープされるということです。この答えにはいくつかの良い例があり ます

varES6コードで使用する理由がわかりません。与えられた変数のスコープを関数全体にしたい場合でもlet、関数ブロックの先頭に宣言を置くことでそれを行うことができますvar。また、forブロックなどでより細かくスコープを設定する場合は、それも実行できます。

ですから、私の本能は、varES6コードを書くときは完全に使用をやめることです。

私の質問は、これについて間違っていますか?よりvarも望ましい合法的なケースはありますletか?


3
私はまだこれを試していません(まだES6コードを書いていないので)が、varこの変数が関数全体にスコープされることを意図していることを意識的な指標として使用することは有用な「自己文書化」規約であるようです。
jfriend00

10
let関数の最上部にステートメントを配置すると、関数全体にスコープを設定することを意図したのと同じくらい明白だと思います。使用varすると、単に最上部に配置するよりも明確になるとは思わない。
カルム

11
正直なところ、唯一の理由varは後方互換性にあると信じています。それがなかったら、彼らはvar完全に削除するかlet、そもそも導入しなかっvarたでしょう。代わりに、セマンティクスをほぼ間違いなく本来あるべきものに変更しました。
ヨルグWミットタグ

2
@RayToalカイル・シンプソンが言うことの97%に同意しますが、彼が使用し続ける理由varは私には薄く見え、飛び回る第3の種類の変数を持つことを保証するのに十分ではありません。let関数の最上部に配置するだけで関数全体にスコープを設定できます。これはvar、ブロックに書き込むよりも意図的にはるかに明確です(そのブロックから持ち上げてブロックの外側で使用できるようにするため) -変)彼はlet、関数にスコープを設定すると、「構文ではなく、単に違いを示す位置になります」と警告していますが、それは良いことだと思います。
カルム

2
@RayToal私もその記事を読んで(この議論を読む直前)、彼の非常に弱いケースに本当に失望しましたvar。維持するために彼が提示する例varは不自然に思えます-そして、重大なコーディングエラーに基づいています。エラーに遭遇してそのようなエラーを修正せざるを得ない方が、それを回避できる言語関数を使用するよりもずっと良いです!次に、クラッシュを防ぐためにすべてをtry / catchでラップすることをお勧めしますか?そのリンクの残りの部分は良好ですが、その特定の部分にはまったく同意しません。
Mörre

回答:


217

ダグ・クロックフォードはletこの時点で彼の講演「The Better Parts」で議論しています。

ポイントは、let誤解の原因を回避することです。ブロックスコープの言語で設定された期待を持つプログラマー向け。ブロックスコープを持っているように見えても、Aにvar関数スコープがあります関数全体で表示される変数を宣言します)。

var マシンで生成されたコードのような極端な場合でもおそらく有用かもしれませんが、私はそこで一生懸命ストレッチしています。

constも新しく、スコープをブロックしている。後はlet x = {'hi': 'SE'}あなたに再割り当てすることができますx後にしながら、const y = xあなたに再割り当てすることはできませんy、それは誤ってあなたの下から出て変化するから何かを続けているので。それはしばしばpreferrableだ。しかし、明確にするために、あなたはまだオブジェクトを変更することができy.hi = 'SO'ますしない限り、凍結します。)

現実的には、あなたの印象はES6にぴったりです:採用letconst。の使用を停止しvarます。

"The Better Parts"の別のパフォーマンスでは、Dougは。の問題を===修正するので==なく、なぜ追加されたのかを説明==してい===ます。


明らかな例

Mozilla Developer Networkは、var意図したとおりに機能しない例を示しています。それらの例は、onclickWebページにハンドラーを設定する現実的な例です。これは小さなテストケースです:

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、ループの終了後に値を持ちます。


6
彼は==の代わりに===を採用することについて同じ答えを与えます。後者は壊れていますが、ES標準化委員会はそれを変更したくなかったので、彼らはそれが何を意味するのかよくわからない===を追加しました==まったく壊れていません。それは単にのように定義することができますequality comparison using coersionチェックアウトgithub.com/getify/You-Dont-Know-JS/blob/master/...
AmmarCSE

13
@AmmarCSEは、暗黙の強制に関するすばらしい39ページのドキュメントです。プログラミング中に誰もがこれらすべてを念頭に置くことができますか?ダグは、stackoverflow.com / a / 359509/1682419に要約されているように、「壊れた」ことを意味していました。これらすべてを予測できますか?[ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101

2
そう、これらの例のほとんどは配列オペランドを含んでいます。toStringを調べたときの結果と、Objectsの実装方法を理解するのは簡単です。しかし、それが壊れていることを意味するものである場合、私はそれがどこから来ているかを完全に見ます。:-)
AmmarCSE

3
可変ではないときはいつでもconstを使用しないのはなぜですか?私は、それは間ではない本当の選択肢を意味letしてvarではなく、間をletvarそしてconst
shabunc

4
var設計どおりに機能しますが、期待する人数ではありません。これはユーザビリティのバグであり、実装のバグではありません。
Jerry101

12

正しいコードを書いていれば、おそらくセマンティックな変更なしですべてのvarステートメントをletステートメントに変えることができるでしょう。

let識別子が表示される範囲を縮小するため、望ましいです。これにより、最初に使用するサイトで変数を安全に宣言できます。

constが望ましいlet。参照を変更する必要がない限り、const宣言を使用します。これにはlet、初期化された変数の存在を減らし、一般的にコードを推論しやすくするという利点があります。参照を変更する必要があるかどうかわからない場合は、const明示的に変更する必要があるとわかるまで、参照を宣言してください。


5

必ずしもあなたが間違っているとは限りませんが、varを使用する場合には注意点があります。基本的に、let開発者がJavaScriptの愚かさを回避するのに役立つはずです(特に名前の競合の場合)。 varは、closes関数スコープに移動したいため、より大きなスコープを持っているようです。関数内のブロックのスコープ内で一時変数を使用できるようにする必要がある場合など、varが必要になる場合がありますlet。簡単に言えば、ES6が導入した時期ですlet


3
varブロック内のtemp は、ブロックスコープではなく、関数全体で使用できます。これは誤解を招く機能です。
Jerry101

1

es6では「let」のみを使用することに同意する傾向があります。AFIK、 "let"を再宣言するとエラーが生成されます(これは良いことです)。 "var"を使用すると、値をオーバーライドするだけです(es5の "strict mode"も処理します)。


-4

let「変数を等しくする」ことを意味します。これは宣言、つまり、初期化と割り当てです。

constもちろん「定数」を意味するのとは対照的に存在します。これは変数の反対です。

他の一部の言語では、オブジェクトを宣言するときに、オブジェクトではなく実際のオブジェクトの接頭辞を使用します(たとえばdef、「関数の定義」の省略形です。「定義」の意味が完全に欠落しています)。

Let このセマンティック不整合をJavascriptに追加します。

論理的には、「let」キーワードの仕事はメモリを割り当てることなので、定数を何かに等しくさせることもできます。

この問題は、varキーワードがconstサポートされる前に導入されたために発生varします。したがって、下位互換性は変数を意味する必要はありません。(定数値を割り当てるためにも使用できます。)

したがって、let間違った位置での導入。字句的にこれが間違っていることを確認するために、彼らはletvs の字句範囲を変更することも決めたvarので、デバッグ時に不整合が最優先されます。

言い換えれば、let人々(言語メンテナーを意味する)がJavascriptがあまりにも一貫性があり、すべてのイディオムと特異性をマスターし、より多くを望んでいると考えたために存在します。

サイドノートは、varブロックをクロージャーとして扱う場合は「矢印」ブロックでは機能しません(ブロックをクロージャーとして扱うvar前に導入されたため)let


6
-1:退屈で役に立たず、主に意見に基づいています。
ジョエルミューラー

フィジーアロンはここで冗談を言っています。
Jerry101

letJavaScriptの同じカテゴリの他のキーワードのトーンと対立するため、字句形式に対する嫌悪感に同情します。それでも、これは質問に答えることはなく、特にうまくいっていません。ダウン投票
アルアンハダッド

3
let開発者がより複雑なことを望んでいるだけではありません。varsをループアンドクローズすると、クロージャーはvarの最後の値を保持しますが、letで同じを行うと、ループ内の各クロージャーがlet上記@ Jerry101の例
TKoL
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.