Javascriptにおけるクローズドとスコープ

8052 ワード

JavaScriptのクローズドとスコープ
転載または引用の場合は、出典を宣言してください.
解決する問題は、メソッドAからメソッドBに定義された変数を使用することです.
クローズド:関数生成時に近くの値を取り込むことができる関数です.
function B() {
    var s = 0;
    return function() {
        return A(s);
    }
};
function A(s) {
    s++;
    console.log(s);
}
var b = B();
b();
1
[Finished in 0.2s]
満足しています.sの値は関数生成時に近くの「値」を捕獲したからです.ちょっと不満ですが、問題を説明できます.sが使われました.そして
  • ソースコードにいくつかの語句を挿入するために追加します.
  • ...
    var b = B();
    b();
    b();//  3 b();
    b();
    b();
    ....
    1
    1
    1
    1
    [Finished in 0.2s]
    これはおかしいですね.なぜですか?なぜいつも1ですか?毎回1を入れるべきですか?私も分かりません
  • は、add方法を追加し、比較を実行する
  • .
    var s = 10;
    function B() {
        var s = 0;
        add = function() {
            s++;
            console.log(s);
        }
    ....
    };
    function A(s) {
    ....
    }
    var b = B();
    b();
    b();
    add();
    add();
    add();
       
    1
    1
    1
    1
    1
    2
    3
    [Finished in 0.2s]
    これはもっとおかしいです.b()方法は毎回1しかないというなら、add方法も1に戻るしかないはずです.もう一つの問題は、add方法が全体的な方法であることに気づきました.もし呼び出したら、変数によってコール先から検索したら、sの値は10であるべきです.結論の1:これにより、add関数が生成されると、関数が生成された時のsの値(var s=0)をキャプチャしたクローズドが生成されることがわかる.
  • では、この関数はいつ生成されましたか?コードには
  • が存在することに留意されたい.
    ...
    var b = B();//          
    ...
    b();
    b();
    したがって、ここでは関数Bのために生成されたところで、add方法はBの中にもあるので、add生成の場所であり、また、add方法は大域的な方法であり、var b=B()がない場合には、関数も実行されるはずです.コードの先頭にはvar s=10がありますので、じゃ、そうですか?コードは以下の通りです
    var s = 10;
    
    function B() {
        var s = 0;
        add = function() {
            s++;
            console.log(s);
        }
        return function() {
            return A(s);
        }
    };
    
    function A(s) {
        s++;
        console.log(s);
    }
    // var b = B();
    // b();
    add();
    add();
    add();
    実行結果は以下の通りです.
    add();
    ^
    ReferenceError: add is not defined
    結果はadd法のnot definedである.結論の2:add方法は大域的な方法であるが、それはB()の中に存在し、B()だけが実行され、add方法が定義されているものに相当する.さもなければ定義されていない.付:最初に自分の考えはB()の方法が定義されていないので、文脈は存在しません.当てずっぽうで,ご指摘を歓迎します.
  • 新しいテスト
  • var b = B();
    b();
    b();
    b();
    add();
    add();
    add();
      
    1
    1
    1
    1
    2
    3
    [Finished in 0.2s]
    また最初の出発点に戻って、ぼんやりとJsの前に立っています.どうすればいいですかこの二つが使うsは同じものではないですか?やっぱり
  • 山を越えて山を越えるadd方法はsの道のadd方法を探してsを探す時、B()の方法の中で生成するため、まず探すのはBのありかの作用の領域で、このように(var s=0)を探し当てることができて、1,2,3回その+の操作に対して実行します.ここでvar s=0を注釈したら、一番外のvar s=10というsを見つけます.この時の作用域は大域作用域になります.得られた結果は11,12,13です.結論の3:変数を探す時、いつも一番近い関数が生成する時の作用域から探し始めて、もし見つけられなかったら上に探して、トップレベル(object->undefined)
  • まで探します.
  • b()メソッドの探索sの道function Bは典型的なクローズドされた書き方であり、関数パラメータの戻り方によって変数が文を実行した後もアクセスできます.上の本から出力されたデータが表示されているように.しかし問題があります.
  • では問題が来ました.なぜadd方法ができて、クローズドによって毎回変わるのが最初の値ですか?本当に最初の出発点に戻ったとしか言えないですね.言っても心が詰まる.JavaScriptの高級なプログラムの設計の中で、それはとても良い大きい本の赤色の本で、人民教育出版社の第3版の第70ページ、パラメーターの章節を伝える中でこのような1段の話を書いていて、結論の4:「ECMAScriptのすべての関数のパラメータは値によって伝達されます.基本型の値の伝達は基本型変数のコピーのように、参照型変数の伝達は参照型データ型変数のコピーのようになります.」と分かりやすく説明しました.()の時はこのような結果です.sは基本的なNumberタイプです.sを使わなければならないなら、どうすればいいですか?
  • は、基本タイプの値転送を参照タイプの値転送
  • に変更する.
    var s = 10;
    
    function B() {
        // "use strict";s
        var s = 0;
        var c = {
            value: 0
        };
        add = function() {
            s++;
            console.log('add...' + s)
        }
        return function() {
            return A(c);
        }
    };
    
    function A(c) {
        c.value++;
        console.log('A...' + c.value);
    }
    var b = B();
    b();
    add();
    add();
    b();
    add();
    b();
    b();
        
    A...1
    add...1
    add...2
    A...2
    add...3
    A...3
    A...4
    [Finished in 0.4s]
    締め括りをつける
    クローズド:関数生成時に近くの「値」を捕獲できる関数です.