[英]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.