将方法转换为将其作为第一个参数的函数的函数

时间:2016-01-22 09:46:32

标签: javascript functional-programming

最初的问题是在JS中使用分隔符拆分字符串,然后从每个结果的两边删除空格。对此的解决方案如下所示:

var mystring = "First thing, Second thing";
var things = mystring.split(",").map(function(s) { return s.trim(); });
// things is now ["First thing", "Second thing"]

这让我觉得如果有一种方法来编写它而不创建一个匿名(或命名)函数来包含修剪。如何编写函数unmethod以便

mystring.split(",").map(unmethod(String.prototype.trim));
// returns ["First thing", "Second thing"]

返回与things相同的数组。换句话说,如何将一些期望this绑定到一个函数中的方法转换为一个函数,该函数接受一个变量并对该变量进行操作,方法与this上的方法相同。

另外,如果我想将参数传递给方法怎么办?例如,如果我想将split映射到字符串数组上,我需要一种方法将它传递给分隔符。

3 个答案:

答案 0 :(得分:1)

所以你想把方法传递给Array.prototype.map

var myarray = ["A|B", "C|D"];

function applyM(key) {
  return function (args) {
    return function (o) {
      return o[key].apply(o, args);
    };
  };
};

var split = applyM("split");

myarray.map(applyM("split")(["|"]));
myarray.map(split(["|"]));

String.prototype.split仍然是一种方法,您只需应用它,因此名称为applyM。通过将keyargs分开,您可以获得灵活性。

修改

applyM的问题是,它处理带有不必要调用的无效方法。由于对象是方法的隐式参数,因此nullary方法很有用。因此,args成为可选参数。这是我不喜欢可选参数或可变参数函数的一个例子。

我看到三个选项:

  1. applyM成为二元函数applyM(key, args),其中args是可选的(并且失去其部分适用性)
  2. 对于nullary方法还有一个applyM0(并且使api膨胀)
  3. applyM成为有状态的功能(并且失去了一些简洁性)
  4. #3的实施:

    function applyM(arity, key) {
      return function (xs) {
        if (xs.length <= arity) {
          return function (o) {
            return o[key].apply(o, xs);
          };
        }
    
        return xs[key]();
      };
    };
    
    var a = ["A|B", "C|D"];
    var split = applyM(1, "split");
    var lower = applyM(0, "toLowerCase");
    var includes = applyM(2, "includes");
    
    a.map(split(["|"])); // [["A", "B"], ["C", "D"]]
    a.map(lower); // ["a|b", "c|d"]
    a.map(includes(["A", 0])); // [true, false]
    

答案 1 :(得分:0)

这可以通过如下定义unmethod来实现:

function unmethod(f, args) {
    return function(x) {
        return f.apply(x, args);
    };
};

args参数是可选的,因此它将按照问题中的描述工作。在这种情况下,可以像这样传递额外的参数:

var myarray = ["A|B", "C|D"];
myarray.map(unmethod(String.prototype.split, ["|"]))
// returns [["A", "B"], ["C", "D"]]

答案 2 :(得分:0)

你可以这样做:

var unmethod = function (callback) {
    return function (s) {
        return callback.apply(s);
    }
};