繁体   English   中英

功能JavaScript:如何实现Function.prototype.not

[英]Functional JavaScript: how to implement Function.prototype.not

我今天早些时候正在研究一些代码,当时我意识到,“嘿!如果我抽象出一个不是匿名函数的布尔的想法并且进入原型函数,那么这段代码会更简洁和语义......”

考虑一个谓词生成器:

function equalTo(n) {
    return function(x) {
        return n==x;
    };
}

所以你可以像这样使用它:

[1,2,3,4,1,2,3,4].filter(equalTo(2)) == [2,2]

现在,我的想法是使谓词“反转”:

Function.prototype.not = function() {
    //???
}

这样你就可以说:

[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]

我对实现的第一次尝试可能非​​常天真:

Function.prototype.not = function () {
    return ! this(arguments);
}

也许它为什么不起作用。

你将如何实现这个功能,为什么?

我只是试图围绕功能性想法,并且知道JavaScript足以知道它可以用来做到这一点,但不是如何。

您的实施不会有多种原因:

  • 您需要返回一个函数,而不是布尔值。
  • 您应该按原样传递参数,而不是包装在数组中。
  • 您应该保留调用该函数的上下文( this关键字)。

我会像这样实现它:

Function.prototype.not = function (context) {
    var func = this;
    return function() { return !func.apply(context || this, arguments); };
}
  • 我返回一个匿名函数( function() { ... }
  • 我调用apply来调用当前上下文中的原始函数和实际参数。
  • 编辑 )免费奖金:我添加了一个可选context参数,将覆盖this回调。

我可能会这样做(但也许有某种命名空间):

function not (x) {
  return !x;
}

function id (x) {
  return x;
}

function compose (/*funcs*/) {
  var args = arguments.length
    ? Array.prototype.slice.call (arguments)
    : [id]
    ;
  return function () {
    var val = args [args.length - 1].apply (null, arguments);
    for (var i = args.length - 2; i >= 0; --i) {
      val = args [i] (val);
    }
    return val;
  };
}

[1,2,3,4,1,2,3,4].filter (compose (not, equalTo (2)));

用你的想法:

function equalTo(n) {
    var fn = function(x) {
        return n == x;
    };
    fn.not = function(x) {
        return n != x; // use this for simpler conditions
        return !fn.apply(this, arguments); // use this for more complex logic
    }
    return fn;
}

所以你的例子会起作用:

[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]

编辑 :你可以写一个辅助函数(可以找到更好的名字),所以not也不需要每次都重新定义:

function generateFnWithNot(fn) {
    return function () {
        var f = fn.apply(this, arguments);
        f.not = function () {
            return !f.apply(this, arguments);
        }
        return f;
    };
}

因此,当您定义函数时,除了包装generateFnWithNot调用之外,您可以将它们定义为正常:

var equalTo = generateFnWithNot(function (n) {
    return function (x) {
        return n == x;
    };
});

equalTo(5) // resolves to function () { return n == 5; }
equalTo(5).not // resolves to function () { return n != 5; } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM