2

prototype独自のスコープを持つ関数を作成したい。このために、匿名関数を使用していますが、オブジェクトのメンバーにアクセスする方法が見つかりません。

これは私が達成しようとしていることの単純化されたバージョンです:

function F() {
    this.counter = 0;
} 

F.prototype.increment = (function() {
    var lastIncrementTime = -1;
    var caller = this; // <--- it fails here because this is the Window object
    return function(time) {
        if (time > lastIncrementTime) {
            caller.counter++;
            lastIncrementTime = time;
            return caller.counter;
        }
        return caller.counter;
    }
})();

f = new F();

f.increment();

Fこれはオブジェクトを参照していないため、失敗することはわかっていfます。

アクセスする方法はありますか?

4

2 に答える 2

6

すぐに呼び出される関数式 (IIFE)自体は 1 回だけ呼び出されます。すべての呼び出しは、最後incrementに残された変数を使用し、再使用しませんvar

callapplyまたはを使用して呼び出しコンテキストを変更します。bind

F.prototype.increment = (function() {
    // this === F.prototype
    // ...
}).call(F.prototype);

このthis例のコンテキストの はインスタンス固有ではなく、プロトタイプになります。


インスタンスが構築されたときに、インスタンス固有のプロパティを独自のクロージャーで初期化する独立した関数がある場合、実際には少し異なることを達成したいようです。これらのタイプのアクションはメモリを少し消費する可能性があるため、一意のデータをあまり保存しないでください。

function F() {
    this.counter = 0;
    this.__init_increment(); // create `this.increment`
}
F.prototype.__init_increment = function () {
    var lastIncrementTime = -1;
    this.increment = function (time) {
        if (time > lastIncrementTime) {
            this.counter++;
            lastIncrementTime = time;
        }
        return this.counter;
    };
};
var f = new F();
f.increment(0); // 1
f.increment(0); // 1
f.increment(5); // 2

この例でthis.incrementは、 はインスタンスごとに異なる関数です。つまり、インスタンスごとに異なるクロージャーがあることを意味します。これらは、インスタンス プロパティを設定するプロトタイプ関数によって生成されます。ジェネレーターはプロトタイプにある必要はありません。インスタンスに適用するときは、呼び出しコンテキストについて覚えておいてください。

于 2013-08-24T21:54:37.723 に答える
2

適切に設定されているvar caller = this無名関数内に移動します。this

于 2013-08-24T21:47:16.753 に答える