【问题标题】:Is it possible to make a functor in JavaScript?是否可以在 JavaScript 中制作仿函数?
【发布时间】:2009-07-14 10:48:50
【问题描述】:

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

【问题讨论】:

标签: javascript functional-programming functor


【解决方案1】:

我相信这就是你想要的:

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

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

或者,关注the Wikipedia example

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

var acc = makeAccumulator(2);

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

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

【讨论】:

  • 哪个“它”。 foo() 示例确实返回未定义。这只是一个例子。累加器示例应该按预期工作。我添加了一个简单的用例。
  • 谢谢。 foo 的例子。我在第二个例子之前评论过。
  • foo 示例没有返回值。我添加了一个 return 以便它应该按预期运行。
【解决方案2】:

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

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

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

不过,在某些现有对象上,不存在仅“实现运算符 ()”的等价物。

【讨论】:

    【解决方案3】:

    您可以将函数视为对象并赋予它们“成员变量”。这里我们在fact 中使用了一个内部函数,但不是仅仅将其声明为局部变量(var loop = ...),而是使用对象语法(fact.loop = ...)将其定义放在函数之外。这让我们实质上“导出”了fact 的内部loop 函数,以便它可以被函数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
    

    【讨论】:

      【解决方案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'

      【讨论】:

        猜你喜欢
        • 2018-12-16
        • 1970-01-01
        • 2017-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-07
        • 1970-01-01
        相关资源
        最近更新 更多