跪求各位大大分享一个更好的解决方法?
发布于 5 年前 作者 QuoniamYIF 3127 次浏览 来自 问答

现在的需求是:

已经从后台返回了JSON数据,如下:

[{
    "c": 1
}, {
    "f": 1
}, {
    "e": 1
}, {
    "y": 2
}]

然后有许多个较为复杂的计算公式,现在取出一个公式,如下: pow( (pow(c+f, 2) + pow(e, 3) + pow(e + y, 2) ), 3/2)

如何快速的替换 c,f,e,y ? 然后我写了一个类似如下的处理代码,但是被老大否决了(PS:当时心中有一万只草泥马飞过)?

"use strict"

let ex1 = "pow( (pow(c+f, 2) + pow(e, 3) + pow(e + y, 2) ), 3/2)"

let returnV = [{
    "c": 1
}, {
    "f": 1
}, {
    "e": 1
}, {
    "y": 2
}]

let Reg

let ex1 = expression
    .replace(/pow/g, "Math.pow")

for (let i = 0; i < returnV.length; i++) {
    let item = returnV[i]
    let key = Object.keys(item)

    Reg = new RegExp(key, 'g')
    ex1 = ex1.replace(Reg, returnV[i][key])
}

console.log(eval(ex1))

求各位大大分享一下有没有更好的处理办法,送上我的膝盖~

12 回复
var pow = Math.pow.bind(Math);
var fn = new Function('c', 'e', 'f', 'y', "return pow( (pow(c+f, 2) + pow(e, 3) + pow(e + y, 2) ), 3/2)");
var data = [{
    "c": 1
}, {
    "f": 1
}, {
    "e": 1
}, {
    "y": 2
}];
var args = {};
data.forEach(function(v, k) {
	Object.assign(args, v);
});

fn(args.c, args.e, args.f, args.y);

这样行不行呢:

let tmp = returnV.reduce((pre, next)=>Object.assign(pre, next), {});
let data = Math.pow((Math.pow(tmp.c + tmp.f, 2) + Math.pow(tmp.e, 3) + Math.pow(tmp.e + tmp.y, 2) ), 3 / 2)
console.log(data);

思路是构造 Function,而不是替换。

@stonephp 我只取了很少的JSON数据,实际上数据要好几百个对象,不止上面的四个

思路是一样

把所有变量(包括pow)assign到global上,构造Function,里面所有的变量就可以直接用…

@stonephp 难道我要在fn里写几百个参数?

借用楼上代码(不过绑定到global不是什么好东西,以前有个东西叫做with)

var fn = new Function("return pow( (pow(c+f, 2) + pow(e, 3) + pow(e + y, 2) ), 3/2)");
var data = [
  {"c": 1},
  {"f": 1},
  {"e": 1},
  {"y": 2}
];

var that = global;

data.forEach(function (v, k) {
  Object.assign(that, v);
});

that.pow = Math.pow.bind(Math);

console.log(fn());

@QuoniamYIF 你可以把表达式里的 c, f, y 这些先替换成 args.c, args.f, args.y

@stonephp@DevinXian 感谢两位大大 膜拜~

借用楼上代码 不改变当前的global的

const util = require('util');
const vm = require('vm');
var data = [
  {"c": 1},
  {"f": 1},
  {"e": 1},
  {"y": 2}
];

var sandbox = {result: 0, pow: Math.pow};

data.forEach(function (v, k) {
  Object.assign(sandbox, v);
});

const script = new vm.Script('result=pow( (pow(c+f, 2) + pow(e, 3) + pow(e + y, 2) ), 3/2)');

const context = new vm.createContext(sandbox);
script.runInContext(context);

console.log(util.inspect(sandbox));

@jiangzhuo 对vm的API不熟悉,用这个包装搞个沙箱再好不过了,赞!之前有个解析nodejs module封装的文章,依稀记得是利用vm模块的

回到顶部