3

実行時に異なる結果を返す次の 2 つのカウンター関数があります。

最初のスニペットでは、counter 関数が変数 letsCount に割り当てられており、関数を実行すると counter 関数の var カウントが更新されるように見えます。

ただし、2 番目のスニペットでは、関数を直接実行してもカウント変数は更新されません。

結果が異なる理由と、関数を返す関数が変数に割り当てられるとどうなるかを説明してください。

スニペット 1

function counter() {
    var count = 0;
    return function() {
        console.log(count++);
    }
}
var letsCount = counter();
letsCount();    // 0
letsCount();    // 1
letsCount();    // 2

スニペット 2

function counter() {
    var count = 0;
    return function() {
        console.log(count++);
    }
}
counter()();  // 0
counter()();  // 0
counter()();  // 0
4

4 に答える 4

2

呼び出すたびcounter()に、独自のスコープ変数を使用して、新しい無名関数インスタンスを作成します。同じ機能を使い続けたい場合は、次のようにする必要があります。

var counter = (function () {
    var count = 0;

    var fn = function() {
        console.log(count++);
    };

    return function () {
        return fn;
    };
})();

counter()();  // 0
counter()();  // 1
counter()();  // 2

単一の無名関数が作成され、スコープ付きfn関数に格納されます。次に、呼び出されたときに によって保持されている値を返す関数を返しますfn

于 2012-11-16T00:10:51.480 に答える
1

スニペット 1スニペット 2は呼び出しが異なります。最初のスニペットには、返された関数への参照があり、その関数はそのスコープを保持しています (クロージャであり、への参照がありますcount)。

2 番目のスニペットは毎回外側の関数を呼び出し、常に新しい関数への参照を返し、新しいcountへの新しいクロージャーを使用します。

于 2012-11-16T00:14:13.493 に答える
0

なぜそのような振る舞いをするのかは、実際には完全に理にかなっています。を呼び出すcounter()()と、最初のcounter()呼び出しが実行され、実質的に変数countが 0 にリセットされます。変数をcounter()に設定すると、実際には返された関数に設定されます。

var letsCount = // (function() {
    // var count = 0;
    return function() {
        console.log(count++);
    }

// })();

次に、を呼び出すとletsCount、外部関数ではなく、返された関数が呼び出されます。

于 2012-11-20T16:40:01.373 に答える
0

最初のケースでは、関数ポインターで参照しています..したがって、コンテキストは保存されます

一方、2 番目のケースでは関数を呼び出していますが、カウントは 0 です。したがって、変数はここでは文脈から外れているので、値が 0 と表示されます。

于 2012-11-16T00:11:59.877 に答える