ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript クロージャーの詳細なグラフィック コードを理解するには 1 分かかります。

JavaScript クロージャーの詳細なグラフィック コードを理解するには 1 分かかります。

黄舟
黄舟オリジナル
2017-03-08 14:14:341083ブラウズ

閉鎖とは何ですか?

まずコードの一部を見てみましょう:

function a(){
    var n = 0;
    function inc() {
        n++;
        console.log(n);
    }
    inc();  
    inc(); 
}
a(); //控制台输出1,再输出2

簡単です。もう一度コードを見てみましょう:

function a(){
    var n = 0;
    this.inc = function () {
        n++; 
        console.log(n);
    };
}
var c = new a();
c.inc();    //控制台输出1
c.inc();    //控制台输出2

シンプルです。

閉鎖とは何ですか?これで閉店です!

別の関数のスコープ内の変数にアクセスできる関数はクロージャです。ここで、inc 関数はコンストラクター a 内の変数 n にアクセスするため、クロージャーが形成されます。

もう一度コードを見てみましょう:

function a(){
    var n = 0;
    function inc(){
       n++; 
       console.log(n);
    }
    return inc;
}
var c = a();
c();    //控制台输出1
c();    //控制台输出2

それがどのように実行されるかを見てください:

var c = couter()、この文 couter() は関数 inc を返します。この場合、この文は var c = inc; と等価です。

c ()、この文は inc(); と同等です。関数名は単なる識別子 (関数へのポインター) であり、() は実行関数であることに注意してください。

次の 3 つの文の翻訳は、var c = inc; inc(); inc(); ですが、最初のコードとは異なりますか? いいえ。

閉鎖とは何ですか?これで閉店です!

教科書のチュートリアルはすべて、最後の段落を使ってクロージャを説明することを好みますが、これが問題を複雑にしていると思います。ここで返されるのは関数名です。Tan Haoqiang の C/C++ プログラミングを見たことがない学生には、() を使用する場合と使用しない場合の違いがすぐには分からないかもしれません。つまり、この記述方法には独自の罠があります。この書き方はより洗練されていますが、それでも問題を単純化したいと思います。コード 1 とコード 2 を見てください。それでも関数呼び出しに苦労しますか? n の値に苦労しますか?

なぜこのように書くのですか?

js の各関数は小さな暗い部屋であり、外部の情報を取得できますが、外部の世界から内部の内容を直接見ることはできません。変数 n を小さな黒い部屋に置きます。 inc 関数を除いて、変数 n にアクセスする方法はありません。また、関数 a の外で同じ名前の変数 n を定義しても、これはいわゆる拡張です。 「カプセル化」 。

関数識別子incを返すのにreturnを使っているのは、inc関数はa関数の外で直接呼び出すことができないので、return incを外にリンクしているためです、これはコード2でもincを外にリンクしています。

よくあるトラップ

これを見てください:

function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
    console.log(funcs[i]());
}

一見、0~9を出力すると思っていましたが、10 10を出力するとは思いませんでした?

ここでの罠は、() が付いた関数が実行関数であるということです。 var f = function() {alert(‘Hi’); の文が続く場合のみ、関数内のコードが実行されます。上記のコードの翻訳は次のとおりです:

var result = new Array(), i;
result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
...
result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
i = 10;
funcs = result;
result = null;

console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
...
console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10

なぜ結果だけが収集され、私は収集されないのですか? i はまだ関数によって参照されているためです。レストランと同じように、皿の数には限りがあるため、ウェイターは空の皿を集めるためにテーブルを巡回しますが、野菜がまだ入っている皿を集めることができますか? もちろん、皿の上の皿を手動で空にすると(= null)、皿は取り去られます。これは、いわゆるメモリリサイクルのメカニズムです。

i の値がどのように保持されるかについては、実際、記事の最初から最後まで読んだ後では、何も心配する必要はありません。皿の上の料理は一切れ食べたら欠けてもいいのではないか?

まとめると

クロージャとは、別の関数の変数を参照する関数であり、変数は参照されるため再利用されないため、プライベート変数をカプセル化するために使用できます。これは長所でもあり、短所でもあります。不必要なクロージャはメモリ消費量を増やすだけです。さらに、クロージャを使用する場合、変数は静的なプライベート変数に似ているため、変数の値が要件を満たしているかどうかにも注意する必要があります。クロージャは通常、さまざまな事柄と混同されていますが、ここでは基本的な事項について説明するためのほんの始まりにすぎません。


以上がJavaScript クロージャーの詳細なグラフィック コードを理解するには 1 分かかります。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。