繁体   English   中英

如何简化用underscore.js编写的这个过滤器?

[英]How to simplify this filter written in underscore.js?

给定是一个具有一系列条件的对象:

var conditions = {
    even: function (i) { return i % 2 == 0; },

    greatherThan: function (i) { return i > 10; },

    inValidRange: function (i) {
        return i > 20 && i < 100;
    }
};

以及从0到39的范围内的数组编号: var numbers = _.range(0, 40);

我想按各种条件过滤numbers 我使用underscore.js来做到这一点:

var result = _.filter(numbers, function(current) {

    return _.all(_.values(conditions), function(f) { 
        return f(current);
    });

});
// returns [ 22, 24, 26, 28, 30, 32, 34, 36, 38 ]

它工作正常,但不幸的是,上面的代码看起来很奇怪,而且非常令人困惑。

如何简化此代码以使其更易读和易懂?

这个辅助函数可能很有用:

_.mixin({
    invokeWith: function() {
        var args = arguments;
        return function(fn) {
             return fn.apply(null, args);
        };
    }
});

如果你的conditions是一个阵列,那也会更好。 您可以使用一组命名函数:

var conditions = [
    function even(i) { return i % 2 == 0; },
    function greaterThan(i) { return i > 10; },
    function inValidRange(i) { return i > settings.validRange.from && i < settings.validRange.to; }
];

或者之前转换它,以便我们可以省略(并且不需要重复调​​用) values函数:

conditions = _.values(conditions);

现在您可以将代码缩短到

var result = _.filter(numbers, function(current) {
    return _.all(conditions, _.invokeWith(current));
});

理解发生的事情可能会更复杂,因为大多数人都必须查找invokeWith函数,但是这个概念更容易理解,因为代码是完全声明的,包含构建自然表达式的所有动词current调用所有条件

如果想要删除外部lambda表达式,它会变得更短但更难理解:

// functional programming FTW :-)
var result = _.filter(numbers, _.compose(_.partial(_.all, conditions), _.invokeWith));

没有必要重写该代码; 把它放在一个命名函数中:

function filterByConditions(values, conditions){
  return _.filter(values, function(current) {

    return _.all(_.values(conditions), function(f) { 
      return f(current);
    });

  });
}

函数中的代码并不复杂,不应该与熟悉underscore.js的人混淆。 如果您认为有必要,可以在函数体中添加注释。 无论哪种方式,当您在其他地方使用该函数时,应该清楚该函数从名称中执行的操作:

var result = filterByConditions(numbers, conditions);

如果你想简化函数的主体,那么不熟悉underscore.js的开发人员仍然可以读取它,你可以用简单的for ... in循环替换_all_values 大多数Javascript开发人员可以在没有使用underscore.js的情况下推断_.filter的作用:

function filterByConditions(values, conditions){
  return _.filter(values, function(current){

    for(condition_name in conditions){

      if(!conditions[condition_name](current)){
        // Condition failed
        return false;
      }

    }

    // All conditions passed
    return true;

  });
}

暂无
暂无

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

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