我正在開發一個 Web 應用程序,管理員可以在其中定義和調整需要根據最終用戶提供的輸入值(數字)進行評估的公式。為了清楚起見,以下是我要排除的簡化示例:const obj = { type: "External wall in contact with the ground", layer: { base: { type: "Reinforced concrete (reinforcement 5 vol.%)", thickness: 100, // <-- user value lambda: 2.3, // <-- user value _r: "{{thickness}}/{{lambda}}/1000", // <-- admin defined r: 0 }, waterproofing: { type: "Bitumen sheets (single layer)", share: 1, // <-- user value _r: "{{share}}", // <-- admin defined r: 0, }, insulation: { type: "XPS", thickness: 100, // <-- user value share: 1, // <-- user value lambda: 0.040, // <-- user value _r: "{{thickness}}*{{share}}/{{lambda}}/1000", // <-- admin defined r: 0 } }}Object.entries(obj.layer).forEach(([key, object]) => { var formula = object._r Object.keys(object).forEach(k => formula = formula.replace(`{{${k}}}`, object[k]) ) obj.layer[key].r = eval(formula)})console.log(obj)這_r是管理員定義的公式。這些{{value}}是最終用戶提供的值。該循環遍歷obj.layer屬性來評估公式并將答案保存在 中r。結果將是這個對象:{ type: 'External wall in contact with the ground', layer: { base: { type: 'Reinforced concrete (reinforcement 5 vol.%)', thickness: 100, lambda: 2.3, _r: '{{thickness}}/{{lambda}}/1000', r: 0.043478260869565216 }, waterproofing: { type: 'Bitumen sheets (single layer)', share: 1, _r: '{{share}}', r: 1 },讓我們跳過我不驗證對象結構并確保所有值都可用的事實。我知道eval()這被認為是“危險的”。一個不太好的選擇是Function()。然而,并不完美。到目前為止,我看到了 3 種可能性:只有管理員可以更改公式。因此,執行惡意代碼的風險非常低。我需要的是驗證/清理這些值(類似isFloat()),僅此而已。使用該mathjs庫,它提供了一個很好的evaluate()功能:
JavaScript 中的動態公式求值:eval() 或 not eval()
冉冉說
2023-09-28 16:41:40