2016-06-30 6 views
5

、このコード例がありますは<a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let" rel="noreferrer">documentation for the <code>let</code> statement in MDN</a>で

は、上の例では、意図したとおりに (匿名)の内部関数の5つのインスタンスが 変数iの5つの異なるインスタンスを参照するためです。

変数iの「五つの異なるインスタンスが存在する理由を私は理解していない。

forループの最初のステートメントは、常に一回実行され、無? のでlet文はのみ実行することになっています一度...コード一度
は、反復の最後に到達したことは、第二文で条件をチェック。

どのように来る、彼らが書いたものによると、各反復上iの新しいインスタンスがありますか?

+0

ないが、私は先週、その動作をテストするために起こったとIEが適切にそれを実装しないことが判明。(クロームはなかった。)ECMA 6仕様で – nnnnnn

+1

、let式があるとき使用、すべての反復は、前の範囲にまで連鎖し新しいレキシカルスコープを作成します。http://www.ecma-international.org/ecma-262/6.0/#sec-for-statement-runtime-semantics-labelledevaluation –

+0

はこれを理解するにはループによって作成された要素をクリックすると何が起こるのかを見てみましょう – Jamiec

答えて

3

let式を使用すると、すべての反復で新しいレキシカルスコープが作成され、前のスコープまでチェーンされます。

これは、すべてのクロージャが異なるインスタンスを取得することを意味します。

これは、ECMA 6 specificationによるとわかりますが、すべてのブラウザで同じように動作します。

パフォーマンスの影響についても不明です。むしろこの機能を慎重に使用したいと思います。

+0

同じ効果を達成するために - おそらくさらに悪い性能で。あなたのお勧めは何ですか? – ftor

+0

@ LUH3417私はちょうど私が異なるブラウザでそのような構成のパフォーマンスについて「わからない」と言っています。たとえば、この問題を見てみると、https://bugs.chromium.org/p/v8/issues/detail?id=4762 –

+0

@ LUH3417クロムのために報告しているとはい、おそらくあやふや-sがパフォーマンスの面でも、悪化しています。だから私はこの時点では何も勧めない方がいいでしょう –

0

Javascriptでは、変数は伝統的に関数スコープです。 for ...ループ文のようなブロックは、新しいスコープを作成しません。

あなたはあなたの関数内のどこvarを使用して変数を宣言する場合(例えば、forループで)、それはスコープのトップhoistingからおかげで一度だけを宣言され、インスタンスは1つだけになります機能範囲全体でそれの

for ...ループ内でコールバックを呼び出すと、問題が発生する可能性があります。

// with hoisting, i is only declared once 
for (var i in items) { 
    // the fn is called items.length times, before any callback is invoked 
    _fetchItems(items[i], function() { 
     console.log("fetched for ", items{i]); 
     // for all callbacks, i is the same value items.length-1 
     // because they are called after the loop is complete 
    }); 
} 

またはあなたの例では:逆に

// with hoisting, i is only declared once 
for (var i = 1; i <= 5; i++) { 

    // with hoisting, item is only declared once 
    var item = document.createElement("li"); 
    item.appendChild(document.createTextNode("Item " + i)); 

    // this function will be called after the for...loop is complete 
    // so i value is unique: 5 + 1 = 6 
    item.onclick = function (ev) { 
     // => always return "Item 6 is clicked" 
     console.log("Item " + i + " is clicked."); 
    }; 
    list.appendChild(item); 
} 

let変数はだけ最寄りのブロック(すなわち中括弧の間で任意のコードセクション。)にスコープされています。

例では、変数iの新しいインスタンスは、for ...ループ内のブロックの実行ごとにと宣言されています。 iは1から5になります。したがって、ブロックの実行は5回、したがって変数の5つのインスタンスがあります。

「期待値1をクリックしました」、「項目2をクリックしました。」、などあなたが求めているもの

+0

'for'ループの最初のステートメントは常に1回実行されるということです。 これを 'for(var i = 1; i ++; i <5){let t = i; ...} 'は何の疑いも生じません。 –

関連する問題