2016-08-01 85 views
4

我正在寻找在循环内部进行动态生成条件的最佳方法。动态生成条件JS

值得千言万语所以这里的样本是我的代码:

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执行! 这是真的不能接受的,知道我要在数千个元素的数组上使用这种类型的东西。

你有没有想法做另一种方式,更快?

回答

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

我想都没有提示字符串操作的替代解决方案。相反,您可以组合功能。通过函数组合而不是字符串操作来构建代码应该不太容易出错 - 并且确实少了'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;}); 
}; 

现在给出一个断言,所有需要返回true的“andArray”,并且其中至少有一个需要返回true谓词的“orArray”,下面的代码做这项工作:

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

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

+0

这真的很好,你为我开启了一种思考一些事物的新方式! 但我希望让用户自己输入比较结果......所以在任何情况下它都是字符串:) –