动态生成条件JS

时间:2016-08-01 17:27:17

标签: javascript

我正在寻找在循环中制作动态生成条件的最佳方法。

一个价值千字的样本,所以这是我的代码:

var condition = "data.label == 'Test'";

for (var key in andArray) {
    condition += "&& " + andArray[key];
}

for (var key in orArray) {
    condition += "|| " + orArray[key];
}

var length = dataArray.length;
var result = [];
for (var i = 0; i < length; i++) {
    var data = dataArray[i];
    if (eval(condition)) {
        result.push(obj);
    }
}

我使用eval()功能,效果很好,但实在太慢了!对于200个元素的数组,此代码需要25ms才能执行! 这是不可接受的,因为我知道我将在具有数千个元素的数组上使用这种东西。

您是否有想法以更快的方式做到这一点?

4 个答案:

答案 0 :(得分:2)

创建一个new Function(),这样字符串只会被解析一次:

var length = dataArray.length;
var result = [];
var fn = new Function('data', 'return ' + whereCondition);

for (var i = 0; i < length; i++) {
    var data = dataArray[i];
    if (fn(data)) {
        result.push(obj);
    }
}

答案 1 :(得分:2)

我想建议一个没有字符串操作的替代解决方案。相反,你可以组合功能。通过函数组合而不是字符串操作来构建代码应该不易出错 - 并且肯定不那么“hacky”(无论这意味着什么......)。

Javascript具有一阶函数,您可以传递(并组合)谓词。谓词是一个返回布尔值的函数。例如:

var isLabelTest = function(obj) {
  return obj.label === 'test';
}

您可以将它们存储为谓词函数,而不是将条件存储为字符串 然后你可以编写一些函数来获取谓词并返回新的谓词:

var binaryAnd = function(predA, predB) {
  return function(obj) {
    return predA(obj) && predB(obj);
  };
};

var binaryOr = function(predA, predB) {
  return function(obj) {
    return predA(obj) || predB(obj);
  };
};

您还可以编写带有谓词数组的函数,并将数组中的所有谓词组合成一个新的谓词:

var and = function(preds) {
  return preds.reduce(binaryAnd, function(obj) {return true;});
};

var or = function(preds) {
  return preds.reduce(binaryOr, function(obj) {return false;});
};

现在给出一个谓词的“andArray”,它们都需要返回true,并且谓词的“orArray”至少有一个需要返回true,下面的代码完成了这项工作:

var results = [];
var combinedPredicate = binaryAnd(and(andArray), or(orArray));
var pushIfCondition = function (obj) {
  results.push(combinedPredicate(obj));
};
dataArray.forEach(pushIfCondition);

最后,请注意,没有必要自己编写用于组合谓词的函数,像ramda这样的库可以提供更有效的实现。

答案 2 :(得分:0)

这是一个简单的例子:

OR动态条件

const conditions = [false, 0, 'blah', 1]; // whatever conditions you like

conditions.reduce((previousCond, actualCond) =>  
previousCond || actualCond, false)); // => 'blah'

我喜欢这一点,因为它表现为真实条件并返回真实值,而不仅仅是布尔值。


如果要返回布尔值,则可以使用:

conditions.some(cond => cond); // => true

如果要使用条件用户Array.every而不是.some

答案 3 :(得分:0)

这是使用filter

的简单技巧

示例1:

> const num = 10
> const rules = []
> rules.push(num > 5)  // true
> rules.push(num % 2 !== 0)  // to check if it is odd number w/c will be "false"
> console.log(rules)
< [true, false]

> rules.filter((rule) => rule === true).length === rules.length
< false  // Did not pass all the conditions

示例2

> const num = 7
> const rules = []
> rules.push(num > 5)  // true
> rules.push(num % 2 !== 0)  // true
> console.log(rules)
< [true, true]

> rules.filter((rule) => rule === true).length === rules.length
< true  // Passed all the conditions