15

我正在尝试创建一个保持状态但用 foo() 调用的函数。
可能吗?

4

4 回答 4

28

我相信这就是你想要的:

var foo = (function () {
    var state = 0;

    return function () {
        return state++;
    };
})();

或者,按照Wikipedia 示例

var makeAccumulator = function (n) {
    return function (x) {
        n += x;
        return n;
    };
};

var acc = makeAccumulator(2);

alert(acc(2)); // 4
alert(acc(3)); // 7

JavaScript 是其中一种语言,恕我直言,它对作为一等公民的功能提供了出色的支持。

于 2009-07-14T10:53:05.157 回答
4

由于 Javascript 函数是一流的对象,因此可以这样做:

var state = 0;
var myFunctor = function() { alert('I functored: ' + state++);};

state变量将myFunctor在其局部闭包中对函数可用。(在本例中为全局)。这个问题的其他答案有更复杂的例子。

但是,在某些现有对象上仅“实现运算符 ()”并不等同。

于 2009-09-19T18:33:49.067 回答
2

您可以将函数视为对象并赋予它们“成员变量”。这里我们在 in 中使用了一个内部函数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
于 2013-11-18T20:28:06.023 回答
-1

您可以使用带有附加函数对象属性的闭包返回函数。这种函子(闭包)的参数可以在初始化后更改,这在构建一些可以稍后运行/配置的计算时很有用。看看下面的例子。这个答案类似于 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'

于 2016-04-13T20:59:24.967 回答