如何在不使用 eval() 的情况下从 javascript for 循环中的字符串创建 if 条件语句

How to create if conditional statement from string within javascript for loop without using eval()

我正在尝试创建一个高级搜索功能以用于产品对象的多维数组。在表单上,​​用户可以选择根据几个不同属性中的数据缩小产品结果范围(例如“'price' < 20 && 'country' == 'France'”,"region == 'New York' && 'vintage' == '2016' && 'qty > 20").变量 data 中的数据格式如下:

    0:
        name: "Kedem Cream Red Concord"
        appellation: "New York"
        country: "United States"
        price: "10.99"
        primarygrape: "Concord"
        qty: "1"

        region: "New York"
        regprice: "10.99"
        sku: "230"
        vintage: "NV"
    1:
        name: "Kendall Jackson Vintner's Chardonnay"

        appellation: ""

        country: "United States"

        price: "14.99"

        primarygrape: "Chardonnay"
        qty: "35"

        region: "California"

        regprice: "18.99"
        sku: "345"

        vintage: "2016"
... continuing on over 10,000 product records

我想我可以很容易地创建一个基于用户表单输入的字符串来总结他们正在搜索的内容。但是,我需要一种安全的方法来评估我的函数中的字符串 returns resultsArray

中的过滤结果

我能够让它与 eval() 函数一起工作,但我知道这既不安全也不高效。我还尝试过将条件放入数组并尝试将其合并到 for 循环中,但我不知道如何让它工作。棘手的部分是,条件可以是涉及以下产品属性的任意数量的东西:名称、国家、价格、primarygrape、数量、地区、年份。并且不同的属性使用不同的运算符(例如国家、地区等使用'==',而数量和价格使用'>'或'<')。

此代码有效,但使用了禁忌eval()函数:

var conditional = "data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";

var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
    if (eval(conditional))
        {
            resultArray.push(data[i]);
        }
    }
}

这不起作用,因为它会导致 Uncaught ReferenceError: data is not defined 错误:

var conditional = "return data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";

var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
    if (new Function(conditional)())
        {
            resultArray.push(data[i]);
        }
    }
}

知道如何动态创建 if 条件语句以便识别 data 变量吗?或者,有更好的解决方案吗?

如果您根据用户输入获取条件,您可以按照自己的喜好设置格式,它不必是字符串。我会推荐一个看起来像这样的数组:

var conditions = [
  {
    property: 'price',
    comparator: '<',
    value: 20
  },
  {
    property: 'country',
    comparator: '=',
    value: 'France'
  }
];

然后您可以使用 filter 方法生成结果数组:

var resultArray = data.filter(function(item) {
  for (var i = 0; i < conditions.length; i++) {
    if (conditions[i].comparator === '=' && 
        item[conditions[i].property] !== conditions[i].value) {
      return false;
    }

    if (conditions[i].comparator === '>' && 
        item[conditions[i].property] <= conditions[i].value) {
      return false;
    }

   if (conditions[i].comparator === '<' && 
        item[conditions[i].property] >= conditions[i].value) {
      return false;
    }
  }
})

Javascript 数组有一个叫做filter的函数,可以用来做你想实现的事情。

例如,您有一个包含数字的数组:

var arr = [1,3,6,2,6]

而您的计划是过滤所有甚至 numbers.You 可以使用 array.filter()。 您需要将匿名函数传递给它。该函数在您有权访问当前元素的每个条目中调用一次。 您需要在此函数中 return 一个布尔值 - true 表示 该元素将在新的过滤数组中

现在完成的过滤所有偶数的示例:

arr.filter(function(element) {return element%2 == 0})

我希望这足以让您继续。 :-) 在下一个片段中,我用你的数据数组做了一个小例子

 var your_data_array = [
 { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" },
        { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" },
        { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" }
 ]
 
 var filtered_array = your_data_array.filter(function(dataElement) {
   return dataElement.country == "United States";
 })
 
 console.log(filtered_array)