状態を保持しているがfoo()で呼び出される関数を作成しようとしています。
出来ますか?
4 に答える
私はこれがあなたが望むものだと信じています:
var foo = (function () {
var state = 0;
return function () {
return state++;
};
})();
または、ウィキペディアの例に従ってください:
var makeAccumulator = function (n) {
return function (x) {
n += x;
return n;
};
};
var acc = makeAccumulator(2);
alert(acc(2)); // 4
alert(acc(3)); // 7
JavaScriptは、IMHOが第一級市民としての機能を優れた方法でサポートしている言語の1つです。
Javascript関数はファーストクラスのオブジェクトであるため、これを行う方法は次のとおりです。
var state = 0;
var myFunctor = function() { alert('I functored: ' + state++);};
state
変数は、ローカルクロージャの関数myFunctor
で使用できます。(この例ではグローバル)。この質問に対する他の回答には、より洗練された例があります。
ただし、既存のオブジェクトに「演算子()を実装する」だけに相当するものはありません。
関数をオブジェクトとして扱い、それらに「メンバー変数」を与えることができます。ここでは、で内部関数を使用していますがfact
、ローカル変数()として宣言するのではなく、var loop = ...
オブジェクト構文()を使用して、関数の外部にその定義を配置していますfact.loop = ...
。loop
これにより、の内部関数を本質的に「エクスポート」してfact
、関数で再利用できるようになりますdoubleFact
。
var fact = function(n) {
return fact.loop(n, 1);
};
fact.loop = function(n, acc) {
if (n < 1) {
return acc;
} else {
return fact.loop(n-1, acc * n);
}
};
var doubleFact = function(x) {
return fact.loop(x * 2, 1);
};
console.log(fact(5)); // 120
console.log(doubleFact(5)); // 3628800
同じ考えを使用して状態を維持することができます。
var countCalled = function() {
console.log("I've been called " + (++countCalled.callCount) + " times.");
};
countCalled.callCount = 0;
countCalled(); // I've been called 1 times.
countCalled(); // I've been called 2 times.
countCalled(); // I've been called 3 times.
それぞれが独自の状態を持つ複数のものをインスタンス化できるようにしたい場合は、次のことを試してください。
var CallCounter = function(name) {
var f = function() {
console.log(name + " has been called " + (++f.callCount) + " times.");
};
f.callCount = 0;
return f;
};
var foo = CallCounter("foo");
var bar = CallCounter("bar");
foo();
foo();
bar();
foo();
bar();
bar();
bar();
console.log(foo.callCount);
console.log(bar.callCount);
出力:
foo has been called 1 times.
foo has been called 2 times.
bar has been called 1 times.
foo has been called 3 times.
bar has been called 2 times.
bar has been called 3 times.
bar has been called 4 times.
3
4
関数オブジェクトのプロパティが付加されたクロージャ戻り関数を使用できます。このようなファンクター(クロージャー)のパラメーターは、初期化後に変更される可能性があります。これは、後で実行/構成できる計算を構築するときに役立ちます。以下の例を見てください。この答えはlimp_chimpに似ています。
function functor() {
var run = function runX() {
return runX.functorParam;
// or:
// return run.functorParam;
};
run.functorParam = 'functor param'; // default value
return run;
}
var f1 = functor();
// call f1
f1(); // 'functor param'
// lets change functor parameters:
f1.functorParam = 'Hello';
// call f1
f1(); // 'Hello'