質問

ECMAScript6に導入 let.

聞いたのですが、これらの記述としての"地方"の変数がまだないように動作しなの var キーワードとなります。

何が違っていたのか?べきであ let 定することが var?

役に立ちましたか?

解決

スコープの規則

主な違いは、ルールをスコープです。 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のバグの主な情報源の一つであった。

別のstackoverflowの質問をhref="https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example">

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: 3各時間funcs[j]();をコンソールに出力された起動します。

人々はループから正しい値をキャプチャするために、すぐに呼び出された関数を作成作成する必要がありましたが、それも毛深いだっます。

巻き上げ

varキーワードで宣言された変数は、それらが宣言される前でも、彼らは彼らの囲みスコープ内でアクセス可能であることを意味ブロックの先頭に「掲揚」されているもののます:

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

run();

その定義が評価されるまで、変数が初期化されていませんしましょう。 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

再宣言

varがでSyntaxErrorを発生させながら、strictモードでは、letは、あなたが同じスコープで同じ変数を再宣言できるようになります。

'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

他のヒント

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>
<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そう、あなたがクリックするたびに6を取得し保持している唯一のカウンターオブジェクトがありますので、ひとつひとつのクリックハンドラは、同じオブジェクトを参照します。

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

<サブ>(クロームと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>
<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>

の違いについて教えてください letvar?

  • 定義された変数を使用 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 が知られていて初めてループがないに関する分析を行っている。しかし、当社の可変 i が知られている全体の機能です。

また、このブロックscoped変数まで知らなかで宣言されていないので吊り上げ.まもなredeclare同じブロックscoped変数のブロックです。このブロックscoped変数に誤差がより世界的には機能的にscoped変数は、吊り上げ、発生しないエラーの場合複数の宣言も行いました。


で安全に使用 let ます。

一部の人々と主張するだろうと述べ、今後までのみ利用しよう明るvar諸表となり互換性のために残されています。JavaScriptのグル カシンプソン非常に精巧な記事かと考えている場合.

しかし、今日はありません。もし実際に、私たちはるかどうかで安全な利用の let ます。その答えは環境により異なり:

  • い書サーバサイドJavaScriptコードNode.js)まで、安心して利用 let ます。

  • だが筆記のclient-side JavaScriptコードを使いのブラウザベー transpiler( Traceur または バベル-ロ)まで、安心して利用 let 決しかしながら、お客様のコードが可能な最適なる。

  • だが筆記のclient-side JavaScriptコード、ノードを使に基づくtranspiler( traceurシェルスクリプト または バベル)まで、安心して利用 let ます。だからブラウザのみについて知transpiledコード、パフォーマンスの欠点を広げることができればすば

  • だが筆記のclient-side JavaScriptコードな使用transpilerを考える必要がありブラウザです。

    まだまだ一部のブラウザをサポートしない let

Support table


どのブラウザを支援

ための最新の概要をブラウザを支援 let 算時に読みこの答えは、 この Can I Use ページ.


* 世界的にも機能的scoped変数を初期化することができ、使用の前に宣言されていなJavaScriptの変数 吊り上げ. この宣言は常に、トップを務める。

** ブロックscoped変数は吊り上げ

ここではいくつかの例でletキーワードでの説明です。

  

letは非常に多くのvarのように動作します。主な違いは、var変数の範囲は全体囲む関数であることである

ブラウザはJavascript 1.7をサポートウィキペディアショーの

この表でます。

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

受け入れ答えは、ポイントが不足しています:

{
  let a = 123;
};

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

let

ブロック範囲

宣言した変数の使用 let キーワードはブロック-scopedすることがでのみご利用いただけ ブロック とした宣言しています。

トップレベル外の機能)

トップレベルに宣言した変数の使用 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

内部ループ

変数宣言 let でループも参照が可能ですので内部のみにこのループを実行します。

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でブロック-scoped、TDZ.が、しかし、二つのものが異なります。

な再割り当

宣言した変数の使用 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

ここでは、2つの(ちょうどクロムのために始まっサポート)との差のための例です。
ここに画像の説明を入力します

var j変数が依然としてループスコープの(ブロックスコープ)外の値を有しているが、let i変数がループスコープのための外部定義されていない。見ることができるように

"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);

いくつかの微妙な違いがあります - letスコープは、より多くの変数のスコープのように振る舞い、多かれ少なかれ、他の言語ではありません。

例えば。それは彼らが、宣言されている前に、彼らが存在しない、外側のブロックにスコープなど。

しかし、それはletは新しいJavaScriptの実装の一部に過ぎないとブラウザのサポートの度合いを変化させたことは注目に値します。

  • 変数のない巻上

    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 このゴミを収集します。しかし、まれてくる可能性があることであJSエンジンもしこのように構成すれば、 click 機能閉鎖全体に渡る。

    しかし、ブロック範囲ではこの膨大なデータ構造のゴミを収集します。

    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);  
    }
    

    ので let 新しい語彙かな環境でのこれらの名称をinitialiser表現はそれ以上の繰り返し処理(previoslyの評価の増分式が、詳細は こちらの.

主な違いは、 範囲 差が ましょう できるだけご利用中の 範囲 この宣言されたように、ループ var アクセスできるのは外側のループです。からの文書に MDN (例からもMDN):

ましょう できる変数を宣言するのに制限の対象範囲をさらにブロック、または表現で使用します。これとは異なり、 var キーワードを定義する変数は世界的に、地域全体の機能に関わらずブロックです。

変数を宣言する ましょう としてその範囲のブロック内で定義され、いずれのサブブロックとなります。このように、 ましょう 作品のようなものだ var.主な違いは、範囲の 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
}`

トップレベルのプログラムと機能 ましょう, とは異なり、 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特徴なされないので、常に向上transpilesでECMA5用バベル。のための詳細情報訪問 バベルサイト

ここで他の人がすでに書かれているものにに追加する例を示します。あなたは、各機能は、単一の数値引数を取り、配列内の引数の合計と関数のインデックスを返す関数の配列、adderFunctionsを作りたいとします。誰かが単純に期待するかもしれないように動作しません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ブロックの繰り返しを越えて延びているので、

上記のプロセスは、機能の所望の配列を生成しません。代わりに、ループの終了時に、各機能の閉鎖にii内のすべての匿名関数のループ(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

この時間は、iforループの各反復でリバウンドです。各関数は、現在の関数の作成時にiの値を保持し、かつadderFunctionsが期待通りに動作します。

さて、画像は2つの動作を混合し、同じスクリプトで古いletと新しいconstvarを混在しないことをお勧めしている理由は、おそらく表示されます。そうすることで、いくつかの見事に混乱のコードで発生することができます。

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ます。

その違いは、 範囲 変数の宣言されています。

実際、数多くの便利な結果の違い範囲:

  1. let 変数のみに見えるその 最寄り囲む ブロック{ ... }).
  2. let 変数のみに使用できるラインのコードで発生する 変数は宣言されたものと その吊り上げ!).
  3. let 変数はredeclaredによるその後の var または let.
  4. グローバル let 変数を付加していないグローバル window オブジェクトです。
  5. let 変数 使いやすい と閉鎖(れんを起こさない レースの条件).

の制約の let 削減の視認性の変数の増加の可能性が想定外の名前の衝突が見つかります。それによるトラックとした理由変数を含む 到達可能性(人再生未使用いたしました。

その結果、 let 変数が起こると考えられている問題が大きなプログラムが独自に開発した枠組みに組み合わせて新しい。

var がなければならないときに便利で使いたい単結合の効果をお使いの場合閉ループ(#5)または宣言する外-可視のグローバル変数コード(#4).の利用 var 輸出するsupplanted場合 export に移動のtranspiler空間の言語です。

1.利用以外の最寄り囲むブロック: このブロックのコードをスローします参照エラーでの使用 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.なredeclaration: 次のコードをみると、この変数の宣言 let なredeclared降:

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*/);
}

...ループの不意に出力"は5"五回:

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

次の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
}
それは私たちがこのような何かを行うことができますので、

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]をカウントします。

機能VSブロック範囲:

主な違い varlet この変数の宣言されて var機能scoped.は機能が宣言されて letブロックscoped.例えば:

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:

第二次機能 testLet が呼び出され、変数バー宣言 let, は、アクセスの if ます。で変数の宣言されて letブロックscoped (aブロックは、コードの間に巻きブラケットe.g if{} , for{}, function{}).

let 変数んの吊上げ:

もう一つの違いと 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 りできるのではなscopedます。このよ命名紛争が取り扱う場合には大量の変数. var できる場合に用いるグローバル変数を明示的にすること window オブジェクトは常に注意深く考える場合には本当に必要です。

また、少なくとものVisual Studio 2015、活字体1.5で、「varが」ブロックで同じ変数名の複数の宣言を可能にし、「せ」ない、と思わます。

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

var x = 1;
var x = 2;

この意志ます:

let x = 1;
let x = 2;

varは、グローバルスコープ(ホイスト可能な)変数である。

letconstスコープブロックである。

  

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

利用の場合 let

let キーワード付きの変数の宣言の範囲のあらゆるものをブロックを入れ { .. } ペア)が含まれる。つまり、let 暗黙のうちにhijacks他のブロックの範囲、その変数宣言です。

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

ばもっと知りたい続きを読む下

最も有名なる質問への対応範囲で十分に正確な使用 letvar 下記のよ

利用の場合 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, 毎ループの繰り返し、変数scopedを自動的にコピーします。

利用の場合 var

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

これは利用の場合 var, 毎ループの繰り返し、変数scopedと共にコピーします。

私は仕様を読めば右クリックletありがたいのも<のhref = "https://stackoverflow.com/questions/592396/what-is-the-purpose-を回避するために活用することができます#592414" 自己実行機能・イン・javascriptの-のプライベートメンバーのみをシミュレートするために使用する>自己呼び出す機能 - コードの可読性を低下させ、の人気のデザインパターン、デバッグを複雑にし、本当を追加していないことコード保護または他の利点は - 多分セマンティクスのために誰かの欲求を満たす除いて、それを使用して停止します。 /暴言

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といくつかのハッキングます:

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)

しようvs var.すべて 範囲.

var変数はグローバル アクセスできるのでは基本的にあふれ、 う変数はグローバル にのみ存在しま載殺しました。

マ例を以下に注意してどのようにライオン(let)可変する行為なのです。丸太;となりの範囲第2回ソフトである。ログです。

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.

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
}

以前すなわち機能とグローバルJavaScriptで唯一2つのスコープがありました。 'let' キーワードでJavaScriptが今block-level変数を導入しています。

の<のhref = "http://www.codingeek.com/tutorials/javascript/es6-let-keyword-to-declare-variable-in、 '聞かせて' キーワードを完全に理解しているために、 -javascript /」のrel = "nofollowをnoreferrer"> ES6:キーワードが役立つのJavaScript のの中で変数を宣言するために「聞かせて」

今、私は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
}

私は人々が、彼らはなど他の言語のようなJavaScriptで同様のスコーピング、ジャワ、C#を、持っていることの後に、ここで聞かせて使用を開始すると思います。

JavaScriptでスコープについての明確な理解ではないと人々は、以前の過ちを作るために使用される。

を巻き上げはletを使用してサポートされていません。

はJavaScriptに存在するこのアプローチのエラーでは削除得ています。

徹底的に ES6を参照してください。 :それをよりよく理解するためにしましょうとのconst

この記事では明らかにVARの違いを定義し、聞かせてとのconst

  

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

     

let、変数のような、再割り当てされてもよいという信号であります   ループカウンタ、またはアルゴリズムの値スワップ。また、信号   変数は唯一それがで定義されていますブロックで使用されることを、   これは、常に関数を含む全体ではありません。

     あなたは、変数を定義するときに

varが利用可能になりまし最も弱い信号であり、   JavaScriptをインチ変数がよく、または再割り当てすることはできませんし、   変数は、全体の機能のために、または単にのために使用してもしなくてもよいです   ブロックまたはループの目的

ます。https://メディア。 COM / javascriptのシーン/ javascriptの-ES6-VAR-レットまたはconstで-ba58b8dcde75#.esmkpbg9bする

上記:

その違いはスコーピング. var はscoped最寄りの 機能 ブロックlet はscopedの 最寄り囲むブロック, は、 で活用することで、低コストで高機能ブロックです。もグローバルの場合外 ブロックです。可能です。:

Example1:

私の両方の事例が機能 myfunc. myfunc 可変 myvar equals10人になりました。初めての例では認した場合 myvar equals10(myvar==10).そして、agian変数を宣言する myvar (現していmyvar変数の使用 var キーワードを割り当てで新しい価値(20).に次の行を印刷し、その価値を自分です。後の条件付きブロックし再度の値を印刷 myvar 私のソフトである。また、出力の myfunc, myvar 価値=20.

let keyword

Example2: 私の第二の例を使用 var キーワード私の条件付きブロックることをここに宣言します myvar を使用 let キーワードとなります。今話 myfunc かの異なる二つの出力: myvar=20myvar=10.

その差は非常に簡単ないeした。

enter image description here

ぜひこの画像は、作成した非常に簡単な例を用いた実機デモンストレーション constlet 変数.ご覧のときに変更してみてください const 変数の場合は、エラー(るオーバーライド'name'は常に'もしくは let 変数の...

最初に宣言します let age = 33, 以降、割り当てその他の価値 age = 34;, で、何をあてたときにエラーが発生した変更してみてください let 変数

私は条件を考えると、例のほとんどは少し圧倒され、 私は違いを個人的に持っていた主な問題は、「ブロック」とは何であるか理解することです。 私が実現し、いくつかの時点で、ブロックは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);

していることができるよう詳細な理解のJavaScriptに渡っ簡単なる研究の一部が含まれての個みによってプラスその他の詳細は異なる視点です。

理解の違い varましょう できやすい違いをわかりやすくする 機能ブロック範囲.

るのかを考えてみましょう、以下の場合:

(function timer() {
    for(var i = 0; i <= 5; i++) {
        setTimeout(function notime() { console.log(i); }, i * 1000);
    }
})();


   Stack            VariableEnvironment //one VariablEnvironment for timer();
                                       // when the timer is out - the value will be the same value for each call
5. [setTimeout, i]  [i=5] 
4. [setTimeout, i]  
3. [setTimeout, i]
2. [setTimeout, i]
1. [setTimeout, i]
0. [setTimeout, i]

####################    

(function timer() {
    for (let i = 0; i <= 5; i++) {
        setTimeout(function notime() { console.log(i); }, i * 1000);
    }
})();

   Stack           LexicalEnvironment - each iteration has a new lexical environment
5. [setTimeout, i]  [i=5]       
                      LexicalEnvironment 
4. [setTimeout, i]    [i=4]     
                        LexicalEnvironment 
3. [setTimeout, i]      [i=3]       
                         LexicalEnvironment 
2. [setTimeout, i]       [i=2]
                           LexicalEnvironment 
1. [setTimeout, i]         [i=1]
                             LexicalEnvironment 
0. [setTimeout, i]           [i=0]

timer() が呼び出される ExecutionContext 作成することができますの VariableEnvironment すべての LexicalEnvironments 各なります。

と簡単な例

機能範囲

function test() {
    for(var z = 0; z < 69; z++) {
        //todo
    }
    //z is visible outside the loop
}

ブロック範囲

function test() {
    for(let z = 0; z < 69; z++) {
        //todo
    }
    //z is not defined :(
}

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

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

それが宣言されるまで、

ただし、LETかのconstで宣言された変数を参照することはできません。あなたはそれが宣言される前にそれを使用しようとすると、例外は実行コンテキストの実行フェーズ中に発生します。今、変数はまだ、メモリ内の実行コンテキストの作成段階の礼儀になりますが、エンジンは、あなたがそれを使用することはできません。

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

エンジンは、現在の実行コンテキストの変数の環境で変数を見つけることができない場合はVARで定義された変数で、それはスコープチェーン(外部環境)を上がると、変数のための外部環境の変数の環境を確認してください。それはそこにそれを見つけることができない場合は、スコープチェーンを探し続けます。これは、LETとconstの場合ではありません。

letの第二の特徴は、それがブロックスコープを導入しています。ブロックは中括弧で定義されています。例としては、ブロックは、ブロックなどのためにあなたがブロックの内側にletで変数を宣言する場合ならば、変数はブロックの内側にのみ使用可能です、機能ブロックを含みます。実際には、ブロックは、このようなforループ内など、実行されるたびに、それは、メモリ内に新しい変数を作成します。

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

それが実行コンテキストに来るとき、

そして、最後に、VARで定義された変数「はこの」オブジェクトに添付されます。グローバル実行コンテキストでは、それはブラウザでウィンドウオブジェクトになります。これはLETまたはconstのためのケースではありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top