「let」と「var」の違いは何ですか?


4543

ECMAScript 6 letステートメントを導入しまし

「ローカル」変数として記述されていると聞きましたが、varキーワードとどのように異なる動作をするのかはまだよくわかりません。

違いは何ですか?いつlet使用すべきvarですか?


105
ECMAScriptは標準でありlet第6版のドラフトに含まれており、おそらく最終的な仕様に含まれます。
Richard Ayotte 2012年

5
ES6機能(letを含む)の最新のサポートマトリックスについては、kangax.github.io / es5-compat-table / es6を参照してください。執筆時点では、Firefox、Chrome、IE11のすべてがサポートしています(ただし、FFの実装はあまり標準的ではないと思います)。
Nico Burns

22
長い間、forループのvarがラップされた関数にスコープされていることを知りませんでした。これを初めて理解したことを覚えていて、それは非常に愚かであると思いました。さまざまな理由で2つをどのように使用できるか、そして場合によってはforループでvarを実際に使用し、それをブロックにスコープしないようにしたい場合があることを知っているので、いくらか力があると思います。
エリックビシャール

1
これは非常に良い読み物ですwesbos.com/javascript-scoping
onmyway133

1
ここでよく説明されている答えstackoverflow.com/a/43994458/5043867
Pardeep Jain '21

回答:


6101

スコープルール

主な違いはスコーピングルールです。varキーワードによって宣言された変数は、直接の関数本体(つまり、関数スコープ)にletスコープが設定され、変数は、(したがって、ブロックスコープ)で示されるすぐ外側のブロックにスコープが設定され{ }ます。

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar);

  {
    let baz = "Bazz";
    console.log(baz);
  }

  console.log(baz); // ReferenceError
}

run();

letキーワードが言語に導入された理由は、関数のスコープであり、JavaScriptのバグの主な原因の1つでした。

別のstackoverflowの質問からこの例を見てみましょう:

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

My value: 3funcs[j]();匿名関数が同じ変数にバインドされているため、呼び出されるたびにコンソールに出力されました。

ループから正しい値を取得するために、すぐに呼び出される関数を作成する必要がありましたが、これもやっかいでした。

巻き上げ

varキーワードで宣言された変数はホイストされますundefinedコードが実行される前に初期化されます)。つまり、宣言される前であっても、それらの囲みスコープでアクセスできます。

function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

let変数は、その定義が評価されるまで初期化されません。初期化の前にそれらにアクセスすると、になりますReferenceError。ブロックの開始から初期化が処理されるまでの間、「一時的なデッドゾーン」にあると言われる変数。

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

グローバルオブジェクトプロパティの作成

トップレベルではlet、とは異なりvar、グローバルオブジェクトにプロパティは作成されません。

var foo = "Foo";  // globally scoped
let bar = "Bar"; // globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

再宣言

厳密モードでvarlet、SyntaxErrorが発生する間、同じスコープで同じ変数を再宣言できます。

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo' is replaced.

let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

23
いつでもブロックを作成できます。function(){code; {let inBlock = 5; }コード; };
平均Joe

177
それでは、letステートメントの目的は、特定のブロックで不要な場合にのみメモリを解放することですか?
NoBugs 2013年

219
@NoBugs、はい、変数は必要な場所にのみ存在することが推奨されます。
バットマン2013年

67
letブロック式let (variable declaration) statementは非標準であり、将来は削除されます、bugzilla.mozilla.org / show_bug.cgi?id = 1023609
Gajus、2014

19
ですから、varを使用することに意味があるとは考えられません。誰かがvarを使用することが望ましい状況の例を教えてもらえますか?
Luis Sieira、2015年

622

letクロージャの問題を回避するためにも使用できます。以下の例に示すように、古い参照を保持するのではなく、新しい値をバインドします。

for(var i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>

上記のコードは、古典的なJavaScriptクロージャの問題を示しています。i変数への参照は、の実際の値ではなく、クリックハンドラクロージャに格納されていますi

6を保持するカウンターオブジェクトが1つしかないため、各クリックハンドラーは同じオブジェクトを参照し、クリックごとに6つを取得します。

一般的な回避策は、これを無名関数でラップiし、引数として渡すことです。このような問題は、以下のコードに示すようにlet代わりにvarを使用することで回避することもできます。

(ChromeおよびFirefox 50でテスト済み)

for(let i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>


54
それは実際にクールです。私は "i"がループ本体の外側に定義され、括弧内に含まれ、 "i"の周りに "クロージャー"を形成しないことを期待します。もちろん、あなたの例はそうではありません。構文の観点からは少しわかりにくいと思いますが、このシナリオは非常に一般的であるため、そのようにサポートすることは理にかなっています。これを取り上げてくれてありがとう。
Karol Kolenda 2015

9
IE 11はをサポートしていますがlet、すべてのボタンに対して「6」を警告します。どのようletに動作することになっていると言うソースはありますか?
ジムハンジカー、2015年

10
:あなたの答えのように見えるが正しい動作ですdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ジム・Hunziker

11
確かに、これはJavascriptでよくある落とし穴であり、なぜlet本当に役立つのかがわかります。ループ内でイベントリスナーを設定する場合i、各反復でローカルにスコープを設定するために、すぐに呼び出される関数式は必要ありません。
エイドリアンモイサ

19
「let」の使用は、この問題を先送りするだけです。したがって、反復ごとにプライベートな独立ブロックスコープが作成されますが、 "i"変数はブロック内の後続の変更によって引き続き破損する可能性があります(イテレーター変数は通常ブロック内で変更されないことを許可しますが、ブロック内の他の宣言されたlet変数は呼び出されたとき、彼らがためである)、および任意の関数がブロック内で宣言することは、他の機能のために「I」の破損値は、ブロック内で宣言することができない、したがって、「I」には同一の参照を同じプライベートブロックスコープを共有します。
ゲイリー、2016

199

違いは何だletとはvar

  • varステートメントを使用して定義された変数は、関数の最初から、それが定義されている関数全体で認識されます。(*)
  • letステートメントを使用して定義された変数はそれが定義された瞬間から、それが定義されているブロックでのみ認識されます。(**)

違いを理解するには、次のコードを検討してください。

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

ここでは、変数jが最初のforループでのみ認識され、前後では認識されないことがわかります。しかし、変数iは関数全体で知られています。

また、ブロックスコープの変数は、ホイストされていないため、宣言する前に不明であることを考慮してください。また、同じブロック内で同じブロックスコープ変数を再宣言することもできません。これにより、ブロックスコープ変数は、グローバルまたは機能的にスコープされた変数よりもエラーが発生しにくくなります。


let今日使用しても安全ですか?

一部の人々は、将来的にはletステートメントのみを使用し、varステートメントは廃止されると主張します。JavaScriptの第一人者であるカイル・シンプソン、彼がそうではないと信じる理由について非常に精巧な記事を書きまし

しかし、今日では、そうではありません。実際、このletステートメントを使用しても安全かどうかを自問する必要があります。その質問に対する答えは、環境によって異なります。

  • サーバーサイドJavaScriptコード(Node.js)をlet記述している場合は、ステートメントを安全に使用できます。

  • クライアント側のJavaScriptコードを記述していて、ブラウザーベースのトランスパイラー(Traceurbabel-standaloneなど)を使用している場合は、letステートメントを安全に使用できますが、コードはパフォーマンスに関して最適ではない可能性があります。

  • クライアント側のJavaScriptコードを記述していて、ノードベースのトランスパイラー(traceurシェルスクリプトBabelなど)を使用している場合は、letステートメントを安全に使用できます。また、ブラウザーはトランスパイルされたコードのみを認識するため、パフォーマンスの低下は制限されます。

  • クライアント側のJavaScriptコードを記述していて、トランスパイラーを使用しない場合は、ブラウザーのサポートを検討する必要があります。

    まだまったくサポートletしていないブラウザもあります:

ここに画像の説明を入力してください


ブラウザのサポートを追跡する方法

letこの回答を読んだ時点でのステートメントをサポートしているブラウザーの最新の概要については、このCan I Useページを参照しください


(*)JavaScript変数がホイストされるため、グローバルおよび機能的にスコープされた変数は、宣言する前に初期化して使用できます。これは、宣言が常にスコープの一番上にあることを意味します。

(**)ブロックスコープの変数は巻き上げられません


14
回答v4に関して:i機能ブロックのどこにでもあります!undefined値を割り当てるまで(巻き上げによる)として始まります!ps:letも(その包含ブロックの最上部まで)巻き上げられReferenceErrorますが、最初の割り当ての前にブロックで参照されると、を提供します。(ps2:私は親セミコロンですが、ブロックの後にセミコロンは本当に必要ありません)。そうは言っても、サポートに関するリアリティチェックを追加してくれてありがとう!
GitaarLAB 2016年

@GitaarLAB:Mozilla Developer Networkによると:「ECMAScript 2015では、letバインディングは変数ホイストの対象ではありません。つまり、let宣言が現在の実行コンテキストの先頭に移動しないことを意味します。」-とにかく、私は間の行動巻き上げの違いを明確にすべき私の答えにいくつかの改良作っlet及びをvar
John Slegers

1
あなたの答えはかなり改善されました(私は徹底的にチェックしました)。コメントで参照した同じリンクには、「(let)変数はブロック開始から初期化が処理されるまでの"一時的なデッドゾーン"にある」とも記載されています。これは、「識別子」(「何か」を指すようにテキスト文字列「予約済み」)関連するスコープですでに予約されていることを意味します。そうでない場合、ルート/ホスト/ウィンドウスコープの一部になります。私にとって個人的には、「巻き上げる」とは、宣言された「識別子」を関連する範囲に予約/リンクすることだけです。初期化/割り当て/変更可能性を除く!
GitaarLAB 2018年

そして.. + 1。あなたがリンクしたカイル・シンプソンの記事は素晴らしい読み物です、ありがとうございます!「一時的なデッドゾーン」、つまり「TDZ」についても明らかです。私がいることMDNに読んだ:私は追加したい一つ興味深いことletconstし、あなたが実際に彼らの追加機能が必要な場合にのみ使用することをお勧め強制/「より多くの仕事で結果(書き込み専用constのような)これらの追加機能をチェックするので、 '(およびスコープツリー内の追加のスコープノード)((current)engine(s)for enforce / check / verify / setup。
GitaarLAB 2018年

1
MDNはIEがletを正しく解釈すると言っていることに注意してください。どっち?developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Katinka Hesselink

146

ここではlet、いくつかの例を使用してキーワードの説明を示します。

letのように機能しvarます。主な違いは、var変数のスコープがそれを囲む関数全体であることです。

ウィキペディアのこの表は、Javascript 1.7をサポートするブラウザーを示しています。

MozillaおよびChromeブラウザのみがサポートしていることに注意してください。IE、Safari、そして潜在的に他の人はそうしません。


5
リンクされたドキュメントからのテキストの重要な部分は、「varのように機能するようにします。主な違いは、var変数のスコープが全体を囲む関数であることです」と思われます。
マイケルバー

50
IEがそれをサポートしていないと言うことは技術的に正しいですが、それがMozillaのみの拡張機能であると言うことはより正しいです。
olliej 2009

55
@olliej、実際にはMozillaはゲームのすぐ先です。ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdfの
Tyler Crompton

@TylerCromptonは、何年もの間予約されている単語のセットです。mozillaが追加されたとき、これは純粋にmozillaの拡張であり、関連する仕様はありませんでした。ES6はletステートメントの動作を定義する必要がありますが、それはmozillaが構文を導入した後に行われました。mozにはE4Xもあります。これは完全に死んでいて、mozだけです。
olliej


112

受け入れられた答えはポイントを欠いています:

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined

19
受け入れられた回答は、その例ではこの点を説明していません。受け入れられた回答は、forループ初期化子でそれを示しただけであり、の制限の適用範囲を劇的に狭めましたlet。賛成。
Jon Davis、

37
@ stimpy77「スコープが最も近い囲みブロックにスコープ指定される」と明示的に示されている。マニフェストのすべての方法を含める必要がありますか?
Dave Newton

6
多くの例があり、それらのどれもが問題を適切に示していませんでした。
Jon Davis

5
この貢献は、「ブロック」が角括弧で囲まれた行のセットである場合があることを示しています。すなわち、それは、制御フロー、ループなどの任意の並べ替えに関連付けする必要はありません
webelo

81

let

ブロックスコープ

letキーワードを使用して宣言された変数はブロックスコープです。つまり、変数は宣言されたブロックでのみ使用できます。

トップレベル(関数の外)

トップレベルでは、を使用letして宣言された変数は、グローバルオブジェクトにプロパティを作成しません。

var globalVariable = 42;
let blockScopedVariable = 43;

console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43

console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined

関数内

関数の内部(ただし、ブロックの外部)のletスコープはと同じvarです。

(() => {
  var functionScopedVariable = 42;
  let blockScopedVariable = 43;

  console.log(functionScopedVariable); // 42
  console.log(blockScopedVariable); // 43
})();

console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

ブロック内

letブロックの内部を使用して宣言された変数は、そのブロックの外部からはアクセスできません。

{
  var globalVariable = 42;
  let blockScopedVariable = 43;
  console.log(globalVariable); // 42
  console.log(blockScopedVariable); // 43
}

console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

ループの内側

letinループで宣言された変数は、そのループ内でのみ参照できます。

for (var i = 0; i < 3; i++) {
  var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4

for (let k = 0; k < 3; k++) {
  let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.

クロージャー付きループ

ループのlet代わりにを使用するとvar、反復ごとに新しい変数が取得されます。つまり、ループ内でクロージャを安全に使用できます。

// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}

一時的なデッドゾーン

一時的なデッドゾーンのため、を使用して宣言された変数は、宣言letされるまでアクセスできません。そうしようとすると、エラーがスローされます。

console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;

再申告なし

を使用して同じ変数を複数回宣言することはできませんlet。また、を使用letして宣言された別の変数と同じ識別子でを使用して変数を宣言することもできませんvar

var a;
var a; // Works fine.

let b;
let b; // SyntaxError: Identifier 'b' has already been declared

var c;
let c; // SyntaxError: Identifier 'c' has already been declared

const

constこれは、letブロックスコープでTDZと非常に似ています。ただし、異なる点が2つあります。

再割り当てなし

を使用して宣言された変数はconst再割り当てできません。

const a = 42;
a = 43; // TypeError: Assignment to constant variable.

値が不変であるという意味ではないことに注意してください。そのプロパティは引き続き変更できます。

const obj = {};
obj.a = 42;
console.log(obj.a); // 42

不変オブジェクトが必要な場合は、を使用する必要がありますObject.freeze()

初期化子が必要です

を使用して変数を宣言するときは、常に値を指定する必要がありますconst

const a; // SyntaxError: Missing initializer in const declaration

51

2つの違いの例を次に示します(Chromeでサポートが開始されたばかりです)。
ここに画像の説明を入力してください

ご覧のとおり、var j変数はまだforループスコープ(ブロックスコープ)外の値を持っていますが、let i変数はforループスコープ外では未定義です。

"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
  console.log(j);
}

console.log(j);

console.log("let:");
for (let i = 0; i < 2; i++) {
  console.log(i);
}

console.log(i);


2
ここでどんなツールを見ていますか?
Barton

20
Chrome開発ツール
vlio20

私はCinnamonのデスクトップアプレットの開発者として、そのような光沢のあるツールに触れたことはありません。
Barton

48

微妙な違いがいくつかありletます。スコープは、他の言語の変数スコープとほぼ同じように動作します。

たとえば、スコープを囲んでいるブロック、宣言されるまで存在しない、などです。

ただし、これletは新しいJavascript実装の一部にすぎず、さまざまな程度のブラウザサポートがあることは注目に値します。


11
ECMAScriptは標準でありlet第6版のドラフトに含まれており、最終的な仕様に含まれる可能性が高いことにも注意する必要があります。
Richard Ayotte

23
それが3年の違いです:D
olliej

4
この質問を解決しただけで、2012年もMozillaブラウザーのみがサポートしているのが現状letです。Safari、IE、Chomeはすべてサポートしていません。
疑似サーヴァント2013

2
偶発的に誤って部分的なブロックスコープを作成するという考えは、ブロックの上部にあるletによって定義された変数を使用するのに適していますletifほんの数行のコード以上のステートメントがある場合、定義されるまでその変数を使用できないことを忘れるかもしれません。素晴らしいポイント!!!
Eric Bishard、2015年

2
@EricB:はいといいえ:「中のECMAScript 2015は、let ホイストませんブロックの先頭に変数をしかし、中に変数宣言結果の前にブロック内の変数を参照。にReferenceError(私注:代わりに、古き良きのundefined)。変数は、ブロックの開始から宣言が処理されるまでの「一時的なデッドゾーン」にあります。」「基になるブロックが1つしかないため、switchステートメント」も同様です。出典:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
GitaarLAB

29

主な違いはスコープの違いですが、letは宣言されたスコープ内でのみ使用できます。たとえば、forループの場合と同様に、varはループの外側などにアクセスできます。MDNのドキュメントから(MDNの例も):

letを使用すると、スコープが限定されている変数を、それが使用されているブロック、ステートメント、または式に宣言できます。これは、変数をグローバルに、またはブロックスコープに関係なく関数全体に対してローカルに定義するvarキーワードとは異なります。

letによって宣言された変数は、そのスコープとして、それらが定義されているブロックと、それに含まれているサブブロックを持っています。このように、letvarと非常によく似ています。主な違いは、var変数のスコープがそれを囲む関数全体であることです。

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}`

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

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

ブロック内で使用する場合、変数のスコープをそのブロックに制限します。スコープが宣言されている関数内にあるvarの違いに注意してください。

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

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

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

ECMA6機能であることも忘れないでください。完全にサポートされていないため、Babel Webサイトなどを使用してECMA5にトランスパイルすることをお勧めします。


24
  • 巻き上げない変数

    letではないホイスト彼らが現れるブロックの範囲全体に。対照的に、var以下のように吊り上げることができます。

    {
       console.log(cc); // undefined. Caused by hoisting
       var cc = 23;
    }
    
    {
       console.log(bb); // ReferenceError: bb is not defined
       let bb = 23;
    }

    実は、@ Bergiあたり、両方varletも巻き上げられています。

  • ガベージコレクション

    ブロックスコープは、letメモリを再利用するためのクロージャとガベージコレクションに関連しています。考えて、

    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });

    clickハンドラのコールバックは必要ありませんhugeDataすべての変数を。理論的には、process(..)実行後、巨大なデータ構造hugeDataがガベージコレクションされる可能性があります。ただし、click関数にはスコープ全体のクロージャがあるため、一部のJSエンジンはこの巨大な構造を維持する必要がある可能性があります。

    ただし、ブロックスコープは、この巨大なデータ構造をガベージコレクションの対象にすることができます。

    function process(data) {
        //...
    }
    
    { // anything declared inside this block can be garbage collected
        let hugeData = { .. };
        process(hugeData);
    }
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
  • let ループ

    letループ内では、それをループの各反復に再バインドできます。これにより、前のループ反復の最後から値を確実に再割り当てできます。考えて、

    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    しかし、交換するvarlet

    // print 1, 2, 3, 4, 5. now
    for (let i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    leta)イニシャライザ式b)各反復(以前はインクリメント式を評価するため)の名前で新しい字句環境を作成するため、詳細はこちらです。


4
それらは巻き上げられますが、(ドラムロール)一時的なデッドゾーンのために巻き上げられていないかのように動作します
Drenai

それでは巻き上げられますが、利用できませんか?それは「巻き上げられていない」とどう違うのですか?
N-ate

うまくいけば、ブライアンまたはベルギがこれに答えるために戻ってきます。letの宣言は引き上げられますが、割り当ては引き上げられませんか?ありがとう!
N-ate

1
@ N-ate、Bergiの投稿1つ紹介します。答えを見つけることができます。
zangw 2017年

興味深いことに、それが巻き上げと呼ばれることもあります。技術的には解析エンジンがそれを事前に取得していると思いますが、すべての意図と目的のために、プログラマーはそれを存在しないかのように扱う必要があります。一方、varの巻き上げは、プログラマーに影響を与えます。
N-ate

19

これは、他の人がすでに書いたものに追加する例です。関数の配列を作成するとしますadderFunctions。ここで、各関数は1つのNumber引数を取り、引数と関数のインデックスの配列の合計を返します。キーワードをadderFunctions使用してループで生成しようとしてもvar、誰かが単純に期待するようには機能しません。

// An array of adder functions.
var adderFunctions = [];

for (var i = 0; i < 1000; i++) {
  // We want the function at index i to add the index to its argument.
  adderFunctions[i] = function(x) {
    // What is i bound to here?
    return x + i;
  };
}

var add12 = adderFunctions[12];

// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000

// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true

上記のプロセスは、関数の目的の配列を生成しません。これは、iスコープがfor各関数が作成されたブロックの反復を超えているためです。代わりに、ループの終わりで、iin each関数のクロージャーは、iのすべての匿名関数のループの終わり(1000)でのの値を参照しadderFunctionsます。これは、私たちが望んでいたことではありません。まったく同じ動作をするメモリ内に1000の異なる関数の配列があります。その後、の値を更新するiと、突然変異はすべてのに影響しますadderFunctions

ただし、次のletキーワードを使用して再試行できます。

// Let's try this again.
// NOTE: We're using another ES6 keyword, const, for values that won't
// be reassigned. const and let have similar scoping behavior.
const adderFunctions = [];

for (let i = 0; i < 1000; i++) {
  // NOTE: We're using the newer arrow function syntax this time, but 
  // using the "function(x) { ..." syntax from the previous example 
  // here would not change the behavior shown.
  adderFunctions[i] = x => x + i;
}

const add12 = adderFunctions[12];

// Yay! The behavior is as expected. 
console.log(add12(8) === 20); // => true

// i's scope doesn't extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined

今回iは、forループの各反復でリバウンドされます。各関数iは、関数の作成時にの値を保持し、adderFunctions期待どおりに動作します。

ここで、2つの動作を混合しているイメージletと、同じスクリプトで新しいものとconst古いものを混合することが推奨されない理由がおそらくわかるでしょうvar。これを行うと、コードが非常に混乱する可能性があります。

const doubleAdderFunctions = [];

for (var i = 0; i < 1000; i++) {
    const j = i;
    doubleAdderFunctions[i] = x => x + i + j;
}

const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];

// It's not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true

これをあなたに起こさせないでください。リンターを使用します。

注:これは、var/のlet動作をループで、また関数クロージャを使用して理解しやすくすることを目的とした指導例です。これは数字を追加する恐ろしい方法でしょう。しかし、匿名関数クロージャでデータをキャプチャする一般的な手法は、他のコンテキストでは現実の世界で遭遇する可能性があります。YMMV。


2
@aborz:2番目の例でも非常にクールな無名関数の構文。これは、C#で慣れていることです。今日は何かを学びました。
Barton、

訂正:技術的には、矢印関数の構文はここ=>説明developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
バートン

3
実際には必要ありませんlet value = i;for声明は、字句ブロックを作成します。
歯ブラシ

17

違いは、それぞれで宣言された変数のスコープにあります。

実際には、スコープの違いには多くの有用な結果があります。

  1. let変数は、最も近い囲みブロック({ ... })でのみ表示されます。
  2. let変数は、変数が宣言されたに発生するコード行でのみ使用できます(たとえホイストされていても!)。
  3. let変数は、後続のvarorで再宣言できませんlet
  4. グローバルlet変数はグローバルwindowオブジェクトに追加されません。
  5. let変数はクロージャーで簡単に使用できます(競合状態を引き起こしません)。

let変数の可視性が低下し、予期しない名前の衝突が早期に発見される可能性が高まることによって課される制限。これにより、到達可能性を含む変数の追跡と推論が容易になります(未使用のメモリの回収に役立ちます)。

その結果、let大きなプログラムで使用したり、独自に開発したフレームワークを新しい予期しない方法で組み合わせたりすると、変数が問題を引き起こす可能性が低くなります。

varループでクロージャーを使用する場合(#5)またはコード内で外部から見えるグローバル変数を宣言する場合(#4)にシングルバインディング効果が必要な場合は、それでも便利です。トランスパイラースペースからコア言語に移行するvar場合、エクスポートにを使用することはできませんexport

1.最も近い囲みブロックの外では使用しない: このコードブロックは、2番目の使用が次のようにx宣言されているブロックの外で発生するため、参照エラーをスローしますlet

{
    let x = 1;
}
console.log(`x is ${x}`);  // ReferenceError during parsing: "x is not defined".

対照的に、var作品の同じ例。

2.宣言前に使用しない:
このコードブロックは、宣言前に使用されるReferenceErrorため、コードを実行する前にスローxされます。

{
    x = x + 1;  // ReferenceError during parsing: "x is not defined".
    let x;
    console.log(`x is ${x}`);  // Never runs.
}

対照的に、var例外をスローせずに解析して実行する同じ例。

3.再宣言なし: 次のコードは、で宣言された変数がlet後で再宣言されない場合があることを示しています。

let x = 1;
let x = 2;  // SyntaxError: Identifier 'x' has already been declared

4.アタッチされていないグローバルwindow

var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link);  // OK
console.log(window.link);  // undefined (GOOD!)
console.log(window.button);  // OK

5.クロージャーでの簡単な使用:で 宣言された変数は、varループ内のクロージャーではうまく機能しません。以下は、変数iがさまざまな時点で持つ一連の値を出力する単純なループです。

for (let i = 0; i < 5; i++) {
    console.log(`i is ${i}`), 125/*ms*/);
}

具体的には、これは出力します:

i is 0
i is 1
i is 2
i is 3
i is 4

JavaScriptでは、変数が作成されたときよりもかなり遅い時間に変数を使用することがよくあります。に渡されるクロージャーで出力を遅延させることによってこれを示すときsetTimeout

for (let i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

...を使い続ける限り、出力は変更されませんlet。対照的に、var i代わりに使用した場合:

for (var i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

...ループが予期せずに「i is 5」を5回出力します。

i is 5
i is 5
i is 5
i is 5
i is 5

5
#5は競合状態が原因ではありません。のvar代わりにを使用することによりlet、コードは次と同等になりますvar i = 0; while (i < 5) { doSomethingLater(); i++; } i。isはクロージャーの外側にあり、doSomethingLater()実行されるまでに、iすでに5回インクリメントされているため、出力はi is 55回です。を使用することによりlet、変数iはクロージャ内にあるため、でi作成された「グローバル」な呼び出しを使用する代わりに、各非同期呼び出しは独自のコピーを取得しvarます。
ダニエルT.

@DanielT .:変数の定義をループ初期化子から引き上げる変換では、何も説明されないと思います。これは単にのセマンティクスの通常の定義ですfor。より正確な変換は、より複雑ですが、古典的なfor (var i = 0; i < 5; i++) { (function(j) { setTimeout(_ => console.log(iは$ {j}です。), 125/*ms*/); })(i); }これは、「関数アクティブ化レコード」を導入して、の各値を関数内のi名前で保存jします。
mormegil 2017

14

次の2つの関数が違いを示していますか?

function varTest() {
    var x = 31;
    if (true) {
        var x = 71;  // Same variable!
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function letTest() {
    let x = 31;
    if (true) {
        let x = 71;  // Different variable
        console.log(x);  // 71
    }
    console.log(x);  // 31
}

13

let 興味深いのは、次のようなことができるからです。

(() => {
    var count = 0;

    for (let i = 0; i < 2; ++i) {
        for (let i = 0; i < 2; ++i) {
            for (let i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

その結果、[0、7]がカウントされます。

一方

(() => {
    var count = 0;

    for (var i = 0; i < 2; ++i) {
        for (var i = 0; i < 2; ++i) {
            for (var i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

[0、1]のみをカウントします。


2
可変シャドウイングが望ましいように振る舞うのを見たのはこれが初めてです。いいえ、letの目的はシャドウイングを有効にすることではありません
John Haugeland '24

1
目的?それは構造体です。好きなように使用できます。興味深い方法の1つはこのようなものです。
Dmitry

13

関数VSブロックスコープ:

との主な違いはvarletで宣言された変数var関数スコープであることです。で宣言された関数letブロックスコープです。例えば:

function testVar () {
  if(true) {
    var foo = 'foo';
  }

  console.log(foo);
}

testVar();  
// logs 'foo'


function testLet () {
  if(true) {
    let bar = 'bar';
  }

  console.log(bar);
}

testLet(); 
// reference error
// bar is scoped to the block of the if statement 

変数var

最初の関数testVarが呼び出されても、で宣言された変数foo varは、ifステートメントの外部から引き続きアクセスできます。この変数fooは、関数のスコープ内のどこでも使用できtestVar ます

変数let

2番目の関数testLetが呼び出されると、で宣言された変数bar letifステートメント内でのみアクセスできます。変数を宣言しているのでletされているブロックスコープのブロックは、例えば波括弧の間にコードです(if{}for{}function{})。

let 変数は上昇しません:

とのもう1つの違いはvarletで宣言された変数let が巻き上げられないことです。例は、この動作を説明する最良の方法です。

巻き上げられlet ない変数:

console.log(letVar);

let letVar = 10;
// referenceError, the variable doesn't get hoisted

変数var 巻き上げられます:

console.log(varVar);

var varVar = 10;
// logs undefined, the variable gets hoisted

グローバルletは接続されませんwindow

letグローバルスコープで宣言された変数(関数にないコード)は、グローバルwindowオブジェクトのプロパティとして追加されません。例(このコードはグローバルスコープにあります):

var bar = 5;
let foo  = 10;

console.log(bar); // logs 5
console.log(foo); // logs 10

console.log(window.bar);  
// logs 5, variable added to window object

console.log(window.foo);
// logs undefined, variable not added to window object


いつlet使用すべきvarですか?

スコープがより具体的であるため、可能な場合はいつでも使用letしてくださいvar。これにより、多数の変数を処理するときに発生する可能性のある名前の競合が減少します。オブジェクトvar上に明示的にグローバル変数を置きたい場合に使用できwindowます(これが本当に必要な場合は常に注意深く検討してください)。


9

また、少なくともVisual Studio 2015、TypeScript 1.5では、 "var"はブロック内で同じ変数名の複数の宣言を許可し、 "let"は許可しないように見えます。

これはコンパイルエラーを生成しません:

var x = 1;
var x = 2;

この意志:

let x = 1;
let x = 2;

9

var グローバルスコープ(ホイスト可能)変数です。

letおよびconstブロックスコープです。

test.js

{
    let l = 'let';
    const c = 'const';
    var v = 'var';
    v2 = 'var 2';
}

console.log(v, this.v);
console.log(v2, this.v2);
console.log(l); // ReferenceError: l is not defined
console.log(c); // ReferenceError: c is not defined


8

使用する場合 let

letキーワードは、どのようなブロックの範囲に変数宣言(一般に取り付ける{ .. }ペア)は、それが中に含まれますが、換言すれば、let暗黙的にその変数宣言するための任意のブロックの範囲をハイジャック。

let変数はwindowグローバルにアクセスできないため、オブジェクト内でアクセスできません。

function a(){
    { // this is the Max Scope for let variable
        let x = 12;
    }
    console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined

使用する場合 var

var ES5の変数のスコープは関数内にあり、変数は関数内で有効であり、関数自体の外では有効ではありません。

var変数はwindowグローバルにアクセスできないため、オブジェクト内でアクセスできます。

function a(){ // this is the Max Scope for var variable
    { 
        var x = 12;
    }
    console.log(x);
}
a(); // 12

もっと知りたい場合は、以下をお読みください

スコープ上で最も有名なインタビューの質問の一つは、またの正確な使用を十分することができますletし、var以下のように。

使用する場合 let

for (let i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 0 to 9, that is literally AWW!!!
        }, 
        100 * i);
}

これは、 let、ループの反復ごとに変数がスコープされ、独自のコピーを持つためです。

使用する場合 var

for (var i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 10 times 10
        }, 
        100 * i);
}

これは、を使用するとvar、ループの反復ごとに変数のスコープが設定され、コピーが共有されるためです。


8

最も基本的な用語では、

for (let i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i not accessible ❌

for (var i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i accessible ✔️

⚡️サンドボックスで遊ぶ↓

letとvarを編集する


7

私は右のそれから仕様を読めばlet ありがたいことも避けるのに活用することができる機能を呼び出す自己 -プライベートメンバーのみをシミュレートするために使用多分誰かさんを満たす除いて-本当のコード保護または他の利点を追加していないこと、コードの可読性を低下させる人気のデザインパターン、デバッグ複雑化をセマンティクスを望んでいるので、使用を中止してください。/ rant

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

「を参照してくださいプライベート・インタフェースをエミュレート


すぐに呼び出される関数式が「コード保護」を提供せず、提供する方法について詳しく説明できますletか?(私はあなたが「自己呼び出し機能」を備えたIIFEを意味すると思います。)
Robert Siemer

そして、なぜhiddenPropertyコンストラクタで設定するのですか?hiddenProperty「クラス」内のすべてのインスタンスに1つだけあります。
Robert Siemer

4

いくつかのハックlet

1。

    let statistics = [16, 170, 10];
    let [age, height, grade] = statistics;

    console.log(height)

2。

    let x = 120,
    y = 12;
    [x, y] = [y, x];
    console.log(`x: ${x} y: ${y}`);

3。

    let node = {
                   type: "Identifier",
                   name: "foo"
               };

    let { type, name, value } = node;

    console.log(type);      // "Identifier"
    console.log(name);      // "foo"
    console.log(value);     // undefined

    let node = {
        type: "Identifier"
    };

    let { type: localType, name: localName = "bar" } = node;

    console.log(localType);     // "Identifier"
    console.log(localName);     // "bar"

ゲッターとセッターlet

let jar = {
    numberOfCookies: 10,
    get cookies() {
        return this.numberOfCookies;
    },
    set cookies(value) {
        this.numberOfCookies = value;
    }
};

console.log(jar.cookies)
jar.cookies = 7;

console.log(jar.cookies)

これはどういう意味let { type, name, value } = node;ですか?タイプ/名前/値の3つのプロパティを持つ新しいオブジェクトを作成し、ノードのプロパティ値でそれらを初期化しますか?
AlainIb 2017年

例3では、例外を引き起こすノードを再宣言しています。これらのすべての例も、完璧に動作しvarます。
Rehan Haider

4

対変数。すべてはスコープについてです。

var変数はグローバルであり、基本的にどこからでもアクセスできますがlet変数はグローバルはなく、閉じ括弧でそれらを削除するまで存在します。

以下の私の例を参照し、ライオン(let)変数が2つのconsole.logsで異なる動作をすることに注意してください。2番目のconsole.logでスコープ外になります。

var cat = "cat";
let dog = "dog";

var animals = () => {
    var giraffe = "giraffe";
    let lion = "lion";

    console.log(cat);  //will print 'cat'.
    console.log(dog);  //will print 'dog', because dog was declared outside this function (like var cat).

    console.log(giraffe); //will print 'giraffe'.
    console.log(lion); //will print 'lion', as lion is within scope.
}

console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.

4

ES6では、varの代わりに2つの新しいキーワード(letおよびconst)が導入されました。

ブロックレベルの減速が必要な場合は、varの代わりにletおよびconstを使用できます。

次の表は、var、let、constの違いをまとめたものです

ここに画像の説明を入力してください


3

letはes6の一部です。これらの関数は、違いを簡単に説明します。

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

3

以下は、「let」と「var」がスコープでどのように異なるかを示しています。

let gfoo = 123;
if (true) {
    let gfoo = 456;
}
console.log(gfoo); // 123

var hfoo = 123;
if (true) {
    var hfoo = 456;
}
console.log(hfoo); // 456

gfoo定義され、let当初にあるグローバルスコープ、と私たちは宣言したときにgfoo内部で再びif clauseその範囲に変更し、新しい値がそのスコープ内の変数に代入されたとき、それは影響を与えませんグローバルスコープを。

一方hfooで定義され、var中に最初にあるグローバルスコープが、私たちは内部でそれを宣言したときに再びif clausevarはそれを宣言するために再び使用されているが、それは、グローバルスコープのhfooを検討します。そして、その値を再割り当てすると、グローバルスコープhfooも影響を受けることがわかります。これが主な違いです。


2

上記のように:

違いはスコープです。varは最も近い関数ブロックletスコープとし、最も近い囲みブロックをスコープとします。これは、関数ブロックよりも小さくすることができます。いずれかのブロックの外側にある場合、どちらもグローバルです。例を見てみましょう。

例1:

私の両方の例では、関数がありますmyfunc。10に等しいmyfunc変数myvarが含まれています。最初の例でmyvarは、10(myvar==10)に等しいかどうかを確認します。はいの場合、キーワードをmyvar使用して変数を宣言し (現在は2つのmyvar変数があります)var、新しい値(20)を割り当てます。次の行で、その値をコンソールに出力します。条件付きブロックの後、もう一度myvarコンソールにの値を出力します。あなたはの出力を見ればmyfuncmyvar値は20に等しいです。

キーワードをしましょう

2 var条件ブロックでキーワードを使用する代わりに2番目の例で、keyword を使用して宣言myvarletます。今、私が呼ぶときmyfunc 私は2つの異なる出力を得る:myvar=20myvar=10

したがって、違いは非常に単純です。つまり、その範囲です。


3
コードの画像を投稿しないでください。将来のユーザー(およびアクセシビリティの懸念)を検索できなくなるため、SOの悪用と見なされます。同様に、この回答は、他の回答がまだ対処していないことを何も追加しません。
イノスティア

2

これらすべてのキーワードで実行コンテキストが重要であるため、これらのキーワードを実行コンテキストにリンクします。実行コンテキストには、作成フェーズと実行フェーズの2つのフェーズがあります。さらに、各実行コンテキストには、可変環境と外部環境(その字句環境)があります。

実行コンテキストの作成フェーズ中、var、let、constは、指定された実行コンテキストの変数環境で、変数を未定義の値でメモリに格納します。違いは実行フェーズにあります。値が割り当てられる前にvarで定義された変数の参照を使用すると、その変数は未定義になります。例外は発生しません。

ただし、宣言されるまで、letまたはconstで宣言された変数を参照することはできません。宣言する前に使用しようとすると、実行コンテキストの実行フェーズ中に例外が発生します。これで、実行コンテキストの作成フェーズのおかげで、変数は引き続きメモリに残りますが、エンジンでは使用できません。

function a(){
    b;
    let b;
}
a();
> Uncaught ReferenceError: b is not defined

varで定義された変数を使用して、エンジンが現在の実行コンテキストの変数環境で変数を見つけられない場合、スコープチェーン(外部環境)を上に移動し、変数の外部環境の変数環境を確認します。そこで見つからない場合は、スコープチェーンの検索を続行します。これはletおよびconstの場合とは異なります。

letの2番目の機能は、ブロックスコープを導入することです。ブロックは中括弧で定義されます。例には、関数ブロック、ifブロック、forブロックなどが含まれます。ブロック内でletを使用して変数を宣言すると、変数はブロック内でのみ使用できます。実際、forループ内などでブロックが実行されるたびに、メモリ内に新しい変数が作成されます。

ES6では、変数を宣言するためのconstキーワードも導入されています。constもブロックスコープです。letとconstの違いは、初期化子を使用してconst変数を宣言する必要があることです。そうしないと、エラーが発生します。

最後に、実行コンテキストに関しては、varで定義された変数が「this」オブジェクトにアタッチされます。グローバル実行コンテキストでは、ブラウザーのウィンドウオブジェクトになります。これはletやconstには当てはまりません。


2

用語とほとんどの例は少し圧倒的だと思います。個人的に私が違いを抱えていた主な問題は、「ブロック」が何であるかを理解することです。ある時点で、ブロックはIFステートメントを除いて中かっこになることに気づきました。{関数またはループの開始ブラケットは、新しいブロックを定義しletます。その中で定義されたものはすべて}、同じもの(関数またはループ)の終了ブラケットの後には使用できません。それを念頭に置くと、理解しやすくなりました。

let msg = "Hello World";

function doWork() { // msg will be available since it was defined above this opening bracket!
  let friends = 0;
  console.log(msg);

  // with VAR though:
  for (var iCount2 = 0; iCount2 < 5; iCount2++) {} // iCount2 will be available after this closing bracket!
  console.log(iCount2);
  
    for (let iCount1 = 0; iCount1 < 5; iCount1++) {} // iCount1 will not be available behind this closing bracket, it will return undefined
  console.log(iCount1);
  
} // friends will no be available after this closing bracket!
doWork();
console.log(friends);


1

今、私は使用してステートメントのブロックに変数のより良いスコープがあると思いますlet

function printnums()
{
    // i is not accessible here
    for(let i = 0; i <10; i+=)
    {
       console.log(i);
    }
    // i is not accessible here

    // j is accessible here
    for(var j = 0; j <10; j++)
    {
       console.log(j);
    }
    // j is accessible here
}

他の言語、Java、C#などのJavaScriptで同様のスコープを持つように、人々はここでletを使い始めると思います。

JavaScriptのスコープについて明確に理解していない人は、以前に間違いを犯していました。

巻き上げは、の使用ではサポートされていませんlet

このアプローチにより、JavaScriptに存在するエラーが取り除かれます。

ES6の詳細:letとconstを参照してください。


詳細については、リンクを参照してください-davidwalsh.name/for-and-against-let
swaraj patil

1

この記事では、var、let、constの違いを明確に定義しています

const 識別子が再割り当てされないことを示す信号です。

letは、ループ内のカウンターやアルゴリズム内の値スワップなど、変数を再割り当てできることを示す信号です。また、変数が定義されているブロックでのみ使用されることを通知します。これは、必ずしもそれを含む関数全体ではありません。

varJavaScriptで変数を定義するときに利用できる最も弱いシグナルになりました。変数は再割り当てされる場合とされない場合があり、変数は関数全体で使用される場合と使用されない場合があります。

https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.