javascript在运行时构建过滤器函数

标签 javascript function

当我在下面详细介绍我的用例(希望不要太多)时,请记住基本问题是“如何在运行时在 javascript 中创建自定义函数?”

我有(可能很大)对象数组,用户可以在这些对象上构建自定义搜索。搜索函数会传递一个格式为

的过滤器数组
[{field:'name', predicate:'contains', modifier:'Joe'}, 
 {field:'type', predicate:'is', modifier:'Boss'}]

在此示例中将返回所有名为 Joe 的 Boss。

为此,我创建了一个过滤函数,将过滤器应用于主列表,如下所示:

var matches = everythingOfThatType;
whereClause.forEach(function(filter) {
switch(filter.predicate) {
    case '=':
    case 'is':
        matches = matches.filter(function(record) { return record[filter.field] == filter.modifier; });
        console.log(filter, matches);
        break;
    case '!=':
    case 'is not':
        matches = matches.filter(function(record) { return record[filter.field] != filter.modifier; });
        console.log(filter, matches);
        break;
    ...

等等。

它工作正常,但现在我遇到了一些粗糙的复杂性(过滤器组合的特殊规则,数组属性的递归过滤等),并且为了性能,最好只迭代所有候选者的列表无论如何,一次。

我理想的解决方案看起来像这样

var filterFunc = magicallyCreateFilterFunc(filters);
var matches = everythingOfThatType.filter(filterFunc);

其中 magicallyCreateFilterFunc() 将具有类似于原始 switch 语句的内容,但不是应用过滤器,而是向函数添加一行,该函数最终将应用于所有对象。然后我可以以紧凑、高效的方式添加所有其他复杂性和递归等。

在我看来,JavaScript 非常适合此类任务(顺便说一句,我对 JavaScript 的了解越深入,我就越欣赏它的深度),但我在第 1 步上有点卡住了:动态定义基于运行时数据的函数。我真的很感激能朝正确的方向插入。

最佳答案

事实证明有一种简单、干净的方法可以做到这一点。当我问这个问题时我不知道哦,很久以前,闭包和过滤器是最好的 friend 。

我可以将过滤器函数添加到数组中,然后使用闭包在数组的每个成员上执行所有函数,而不是在 switch 语句中应用过滤器。

所以我上面的 switch 语句看起来更像

var buildFilterList = function(whereClause) {
    var filterFunctions = [];
    whereClause.forEach(function(filter) {
        switch(filter.predicate) {
            case '=':
            case 'is':
                filterFunctions.push((function(field) { return function(record) { return record[filter.field] == filter.modifier; })})(field));
                break;
...

这给了我一个应用于每个元素的函数列表,每个元素都在一个包含它应该应用于的字段的闭包中。更复杂的过滤函数可能有更多的参数。现在,如何有效地获取过滤器列表并应用它们?再次关闭。

var filterApplicator = function(filters) {
    return function(item) {
        var passed = true, i = 0, filterCount = filters.length;
        for (i = 0; passed && i < filterCount; i++) {
            passed = filters[i](item);
        }
        return passed;
    }
}

var filterFunctions = buildFilterList(whereClause);
matches = everythingOfThatType.filter(filterApplicator(filterFunctions));

filterApplicator() 返回一个将应用于原始数组中每个元素的函数。该函数位于包含过滤器函数数组的闭包中,因此它所要做的就是循环这些函数并将它们应用于元素,直到失败为止。

(需要注意的是,我还没有测试过这个确切的语法,但基本概念是我想在这里传递的。)

关于javascript在运行时构建过滤器函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21788907/

相关文章:

函数默认参数和命名值

php - Javascript 函数未定义

javascript - (为什么)使用类似 jQuery 的选择器并执行其中一个方法比查找命名函数更快?

javascript - 尝试在用户点击下落 block 时为 webgl 提供随机颜色

javascript - 我无法在 Node.js 中的 readFile() 回调中更新对象属性

javascript - 获取一段文本中最后一行的宽度

javascript - 将函数视为值时是否会忽略 DOM 命令?

javascript - 在 AngularJS Controller 中声明函数的方法(controllerAs 方法)

javascript - AngularJS 中 $on 中的上下文不正确

javascript - 选择数组成为对象属性