javascript eval() 方法在过滤时降低了性能
javascript eval() method is degrading the performance while filtering
我正在从过滤器数组创建一个 where 子句字符串。
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var raw_data_length = raw_data.length
, filtered_data = [];
for(var i = 0; i < raw_data_length; i++) {
if (eval(where_clause_string)) {
filtered_data.push(raw_data[i]);
}
}
然后,我遍历作为对象数组的数据并仅返回通过真值测试的那个对象。
它给出了预期的结果,但性能却一塌糊涂。仅过滤 1500 行需要约 2-3 秒。如果不使用 eval() 对条件进行硬编码,则过程非常快。
实现此目标的替代方法是什么?
另一种方法是构建一个函数:
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var evaler = new Function('raw_data', 'i', "return "+where_clause_string);
var raw_data_length = raw_data.length
, filtered_data = [];
for(var i = 0; i < raw_data_length; i++) {
if (evaler(raw_data, i)) {
filtered_data.push(raw_data[i]);
}
}
如果你想更进一步,你可以使用Array.prototype
的filter
功能。它还将确保函数生成不是去优化的可能原因(参见 Optimization Killers):
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var filtered_data = raw_data.filter(new Function(
'v', "return "+where_clause_string.replace(/raw_data\[i\]/g,'v')
));
但通常最好从结构化数据开始,而不是要评估的原始字符串。使用我建议的函数可以获得更好的性能,但您仍然会遇到字符串代码的维护、可读性和安全性问题。也许它可以像
var criterium = {
ok_cities:['SACRAMENTO','CITRUS HEIGHTS'],
nok_cities:[]
};
var raw_data_length = raw_data.length,
filtered_data = [];
for (var i = 0; i < raw_data_length; i++) {
// fill all param with values some may filled above the for statement
var param1 = true,
param2 = ['SACRAMENTO', 'CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1,
param3 = false,
param4 = [].indexOf(raw_data[i]['city']) === -1,
param5 = false;
if (param1 && param2 || param3 && param4 || param5) {
filtered_data.push(raw_data[i]);
}
}
我正在从过滤器数组创建一个 where 子句字符串。
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var raw_data_length = raw_data.length
, filtered_data = [];
for(var i = 0; i < raw_data_length; i++) {
if (eval(where_clause_string)) {
filtered_data.push(raw_data[i]);
}
}
然后,我遍历作为对象数组的数据并仅返回通过真值测试的那个对象。
它给出了预期的结果,但性能却一塌糊涂。仅过滤 1500 行需要约 2-3 秒。如果不使用 eval() 对条件进行硬编码,则过程非常快。
实现此目标的替代方法是什么?
另一种方法是构建一个函数:
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var evaler = new Function('raw_data', 'i', "return "+where_clause_string);
var raw_data_length = raw_data.length
, filtered_data = [];
for(var i = 0; i < raw_data_length; i++) {
if (evaler(raw_data, i)) {
filtered_data.push(raw_data[i]);
}
}
如果你想更进一步,你可以使用Array.prototype
的filter
功能。它还将确保函数生成不是去优化的可能原因(参见 Optimization Killers):
var where_clause_string = "(((true && ['SACRAMENTO','CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1) || (false && [].indexOf(raw_data[i]['city']) === -1)) || false)";
var filtered_data = raw_data.filter(new Function(
'v', "return "+where_clause_string.replace(/raw_data\[i\]/g,'v')
));
但通常最好从结构化数据开始,而不是要评估的原始字符串。使用我建议的函数可以获得更好的性能,但您仍然会遇到字符串代码的维护、可读性和安全性问题。也许它可以像
var criterium = {
ok_cities:['SACRAMENTO','CITRUS HEIGHTS'],
nok_cities:[]
};
var raw_data_length = raw_data.length,
filtered_data = [];
for (var i = 0; i < raw_data_length; i++) {
// fill all param with values some may filled above the for statement
var param1 = true,
param2 = ['SACRAMENTO', 'CITRUS HEIGHTS'].indexOf(raw_data[i]['city']) > -1,
param3 = false,
param4 = [].indexOf(raw_data[i]['city']) === -1,
param5 = false;
if (param1 && param2 || param3 && param4 || param5) {
filtered_data.push(raw_data[i]);
}
}