著者:HerryLo
オリジナルの固定リンク: HTTPS://github.com/AttemptWeb/Record ...
恥ずかしい、私は私が完全に閉鎖を理解思っ前に、障害が発生した強制的にロードされ、その後、私は間違った答えだ、問題の閉鎖が発生し、今実際にはなかったことを発見し、-ing答えをすぐに開いた本。
0,1,2を印刷することが望ましい場合がある、次のコードを、ループ配列でインポート機能を参照してください。
関数FUNC(){
VARのARR = []; ため(VARは、I = 0; iは< 3; iは++){ ARR。プッシュ(()=> { コンソール。ログ(I);})} 戻りARR} VAR結果= FUNC()。結果。forEachの((アイテム)=> { アイテム();})<! -打印信息三个3 - > // 3
私の無名関数は同じレキシカルスコープを共有しているため、図3に示すように、印刷中に発見されました。匿名通話機能変数配列は、可変ブロックレベルスコープVAR宣言が存在しない場合、iの値は、forループの最後の点Iを有しています。
次のコードを解決する、上記の問題を解決することができることができますまたは閉鎖して上記の問題を解決します:
<! -プログラム- >
//のlet使用して変数を宣言 、関数FUNC(){ VARのARRを[] =; (のためのIましょう= ;私は0 < ; 3、私は。{++)ARR。プッシュ(()=> { コンソール。ログ(I);})} の戻りARR} VAR結果= FUNC(); 結果。forEachの((項目)=> { 項目();})<! -オプションII - > //使用閉じパッケージ関数FUNC(){ VARのARR = []; のための(VARのI = 0;私は< 3; Iは++){(関数(){ ARR。プッシュ(()=> { コンソール。(i)をログ;})})()} 戻りARR} VAR結果= FUNC()。結果。forEachの((アイテム)=> { アイテム();})
解決されたと思った、と他の質問を考えました!上記のスキームと第2の方式で実行することができ、あなたはオプションIIの結果は、WTを3 3をプリントアウトすることがわかりますか?あなたは0,1,2を印刷し、どのようにではないではないでしょうか?
クロージャスコープチェーン
オプション1は、問題を解決するために使用スコープを聞かせて、もちろん問題ありません。第2の方式では、クロージャの使用は、変数iのスコープの問題を解決するために、それは無効クロージャを思わ。
スキームII演技閉鎖で変数民営化され、閉鎖スコープチェーン、私が破壊されていない変数を保存します。閉鎖のためのスコープは、胡Yuの表示することができます理解していない 深さのJavaScriptの実行コンテキスト と 閉鎖のJavaScriptの深さを。第2の方式は、私たちが望む結果ではない、その理由は、私が引き起こしたクロージャのスコープを理解していないということです。
<! -方案三- >
関数FUNC(){ VARのARR = []; ため(VAR iは= 0; iは< 3; iは++){(関数(I){ ARR。押す(()=> { コンソール。ログ(I);})})(I)} 戻りARR} VAR結果= FUNC()。結果。forEachの((アイテム)=> { アイテム();})
これらは私がオプションIIの問題を解決し、匿名関数のパラメータに追加されますソリューションです。
説明を容易にするため、私はFN1と呼ば稼働から無名関数になり、短いFN2の匿名コールバック関数をARR:さんはどのように問題に詳しく説明しましょう。もちろん、三つの機能ARR FN2三つの異なる機能です。
関数のスコープチェーン
fn2函数作用域链 : {
fn2函数变量和参数 , fn1函数变量&&参数 , func函数变量&&参数 , 全局作用域变量
}
あなたは、関数FN1自走funcを関数を呼び出した場合、リターンが出ARRながら、変数ARRは、3つのFN2機能を注入すること。この時点で閉鎖は、スコープチェーンが形成されています。
FN2機能を使用すると、関数funcの変数iを見つけるまで、私は、VAR宣言されているので、私は、もう一度Fn1機能は、現時点では、機能とFN2私には存在しません継続的に上向きに配列の検索を実行し、ブロックレベルのスコープは、3共有機能FN2存在しません私は。(実際には、この場所は少し反復的であり、非常に始まり、新しいものの出現を説明するが、ここでは、おそらく閉鎖スコープチェーンです)。
通常の関数呼び出しの後、スコープチェーンが破壊されているが、クロージャの存在は、対応するスコープチェーンが保存されます。ARRのFN2機能範囲は、基本的にチェーン範囲を形成する、スコープチェーンが一方向である、ルックアップすることにより、外部に内側に見えます。スコープチェーンは、ローカルおよびグローバル変数、関数パラメータを保存しました。
オプションIIとIIIオプションの比較
//方案二
関数FUNC(){ VARのARR = []; ため(VAR iは= 0; iは< 3; iは++){(関数(){ ARR。押す(()=> { コンソール。ログ(I);})})()} 戻りARR} VARの結果= FUNC(); 結果。forEachの((アイテム)=> { アイテム();})
FN2機能に最初の自分自身の関数スコープを探しますARRそれは私が、私はそれをプリントアウトします関数funcで変数を見つけるまで探し続けて存在していない、結果の呼び出しを横断しながら、今回のFUNC:今すぐオプションIIを見てこの関数は3サイクル、FN2のARRのための3つの機能、前掲、プリント3三回を持っているので、私は、3に等しい変数を有しています。
//方案三
関数FUNC(){ VARのARR = []; ため(VAR iは= 0; iは< 3; iは++){(関数(I){ ARR。押す(()=> { コンソール。ログ(I);})})(I)} 戻りARR} VAR結果= FUNC()。結果。forEachの((アイテム)=> { アイテム();})
オプション3で:結果の呼び出しを横断しながら、FN2機能の編曲が最初に自分自身の関数スコープを探します、私はその後、私は、私がプリントアウトされますFN1関数パラメータを見つけるまで探し続けて存在していません。3つの匿名関数があるので、関数のパラメータは0,1,2です。
終了:クロージャを形成する際にここで実際には、あなたが第2の方式における基本的な問題を理解することができ、実際には、問題の閉鎖スコープチェーンは、スコープチェーンに関連する閉鎖が保存されます。あなたが本当にクロージャを理解していれば、私のように、私は問題に会ったことがない、自分自身へのレッスンも。私たちが指摘できるという希望を書くための悪い場所では、ここに記事への参照リンクです。
(上記の内容は、あなたの不快感の原因となる場合は、胡湯のブログを参照することができます)
参考記事:
PS:あなた自身の個人的な公共の番号をプッシュする方法:Yopai、私たちが興味を持っている時間から時間に毎週更新、従うことができ、世界を共有する喜びを増やすことができます