2017-01-08 2 views
-2

これら3つのコードの違いを説明できますか?彼らは私と同じように見えますが、出力は異なります。JavaScriptでクロージャを使用するときの範囲内の変数の値

1:

var i; 

function print(){return function(){console.log(b)}}; 

function doSetTimeout(b){setTimeout(print(),2000);}; 

for(i=0;i<10;i++){doSetTimeout(i)} 

2:

var i; 

function print(){console.log(b)}; 

function doSetTimeout(b){setTimeout(print,2000);}; 

for(i=0;i<10;i++){doSetTimeout(i)} 

3:第3の期待値を返している間

var i; 

function doSetTimeout(b){setTimeout(function(){console.log(b)},2000);}; 

for(i=0;i<10;i++){doSetTimeout(i)} 

第2は、未定義としてBを返しています。

+0

ところで、のようなブロック文の後にコロンが不要、 '{}; 1,2と' –

+0

、 print関数に 'b'を渡していません。 – Jorg

+0

' doSetTimeout'の中で 'print'を動かすことができます。そして' b'はローカル変数です。 –

答えて

0

あなたが与えた最初の2つの例では、print()にbを渡していないので、printはその変数をその字句の親を見て見つける方法がありません。

printをパラメータとして関数の値を渡すと、クロージャは実行されません。setTimeout()が定義され、print()が実際に呼び出される場所で発生します。だからあなたはあなたが思っている文脈にアクセスすることはできません。

はと定義されているため、最後の例ではが実行されている関数の中で匿名関数が既に定義されているので、bが利用可能です。

"与えられた実行コンテキストが関数定義に遭遇すると、現在のVariableEnvironmentを参照する[[scope]]という名前の内部プロパティを持つ新しい関数オブジェクトが作成されます(ES 5 13.0 -2)

すべての関数は[[scope]]プロパティを取得し、その関数が呼び出されると、scopeプロパティの値がVariableEnvironmentの外部語彙環境参照(またはouterLex)プロパティに割り当てられます(ES 5 10.4.3.5-7)このようにして、各VariableEnvironmentはその字句親のVariableEnvironmentから継承します。このスコープチェインは、グローバルオブジェクトから始まる字句階層の長さを実行します。

出典:また

https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/

良い読み出し:

http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

関連する問題