JavaScript - 对条件使用eval() - 是否正确?

use*_*od2 12 javascript json

我有JSON数据,我正在搜索使用filter:

myJsonData.filter(function (entry) { return (entry.type === 'model' || entry.type === 'photographer' ); });
Run Code Online (Sandbox Code Playgroud)

现在我没有在返回后指定这些条件,而是创建了一个类似的字符串(因为我希望有一个预先创建的搜索条件列表),然后使用eval():

myJsonData.filter(function () { return eval(stringToSearch) ; });
Run Code Online (Sandbox Code Playgroud)

这似乎有效.但是,我只是想确认一下,这是正确的用法吗?这样做有任何风险/问题吗?

我希望能够灵活地进行任何类型的搜索,例如:

filter

这就是我创建一个单独的类来创建该字符串的原因.

tri*_*cot 8

为了避免eval您将用户输入(通过按钮或其他)转换为过滤器.这些过滤器每个数据属性有一个过滤器(即每个位置,类型,级别......).其中一个过滤器可以是值列表,也可以是自由文本单值.

这是一个带有示例数据集的示例实现,没有任何性感的输入/输出小部件,...只是演示过滤算法的最低限度:

// The sample data to work with:
var data = [
    { location: "ny", type: "model", level: "advanced", name: "Jack" },
    { location: "ny", type: "model", level: "beginner", name: "Fred" },
    { location: "sf", type: "model", level: "experienced", name: "Helen" },
    { location: "sf", type: "photographer", level: "is advanced", name: "Stacy" },
    { location: "sf", type: "photographer", level: "advanced experience", name: "Joy" },
    { location: "ny", type: "photographer", level: "beginner++", name: "John" },
    { location: "sf", type: "model", level: "no experience", name: "Jim" },
    { location: "ny", type: "photographer", level: "professional", name: "Kay" },
];

// A global variable to maintain the currently applied filters
var filters = { type: [], location: [], level: "" };

// Capture user selections and translate them to filters
// Type 1: multiple selections from a closed list of values:
document.querySelector("#seltypes").addEventListener("change", function() {
    filters.type = [...this.options].filter(option => option.selected).map(option => option.value);
    refresh();
});

document.querySelector("#sellocations").addEventListener("change", function() {
    filters.location = [...this.options].filter(option => option.selected).map(option => option.value);
    refresh();
});

// Type 2: free text filter:
document.querySelector("#inplevel").addEventListener("input", function() {
    filters.level = this.value;
    refresh();
});

function refresh() {
    // This is the actual filtering mechanism, making use of the filters variable
    let result = data;
    for (let prop in filters) {
        let value = filters[prop];
        if (!value.length) continue; // If this filter is empty: don't filter
        result = Array.isArray(value)
            ? result.filter(entry => value.some(type => entry[prop] === type))
            : result.filter(entry => entry[prop].includes(value));
    }
    // No effort done here on the output format: just JSON :-)
    document.querySelector("#output").textContent = JSON.stringify(result, null, 2);
}

// Start 
refresh();
Run Code Online (Sandbox Code Playgroud)
td { vertical-align: top }
Run Code Online (Sandbox Code Playgroud)
<b>Filters (Ctrl to multi select):</b>
<table>
<tr><th>Types</th><th>Locations</th><th>Level</th></tr>
<tr><td>
  <select multiple id="seltypes" size="2">
    <option value="model">Model</option>
    <option value="photographer">Photographer</option>
  </select>
</td><td>
  <select multiple id="sellocations" size="2">
    <option value="ny">New York</option>
    <option value="sf">San Francisco</option>
  </select>
</td><td>
  <input id="inplevel">
</td></tr></table>

<pre id="output"></pre>
Run Code Online (Sandbox Code Playgroud)