在小程序的开发过程中,开发者可能会遇到需要使用动态执行代码的情况,而eval函数因其能够执行字符串中的JavaScript代码,常被视为一种解决方案。然而,在小程序的开发规范中,明确禁止使用eval函数。本文将探讨小程序不能使用eval的原因,并提供一些替代方案
export function evalMath(exp: string) {
let express: any = exp.replace(/\s/g, "");
let expArr: any = [];
let symbolStack: any = [];
let operatorNumber:string = "";//表示临时运算数
let operator:string = "";//表示临时运算符
for (let i = 0; i < express.length; i++) {
if (express[i] == "(") {
symbolStack.push(express[i]);
}
else if (express[i] == ")") {
while (symbolStack[symbolStack.length - 1] != "(") {
expArr.push(symbolStack.pop())
}
symbolStack.pop();
}
else if (isNumber(express[i])) {
operatorNumber += express[i];
if (i == express.length - 1) {
expArr.push(operatorNumber);
operatorNumber = "";
}
else if (express[i + 1] == ")") {
expArr.push(operatorNumber);
operatorNumber = "";
}
}
else {
if (operatorNumber !== "") expArr.push(operatorNumber);
operatorNumber = "";
operator = express[i];
if (symbolStack.length === 0) symbolStack.push(operator);
else if (symbolStack[symbolStack.length - 1] === "(") symbolStack.push(operator);
else if (getOperatorPriority(operator) > getOperatorPriority(symbolStack[symbolStack.length - 1])) {
symbolStack.push(operator);
}
else {
expArr.push(symbolStack.pop())
if (symbolStack.length == 0 || symbolStack[symbolStack.length - 1] == "(" || getOperatorPriority(operator) > getOperatorPriority(symbolStack[symbolStack.length - 1])) {
symbolStack.push(operator);
}
else {
let max = symbolStack.length - 1;
while (getOperatorPriority(operator) <= getOperatorPriority(symbolStack[max])) {
expArr.push(symbolStack.pop())
if (max > 0) max--;
else {
symbolStack.push(operator)
break;
}
}
}
}
operator = "";
}
}
symbolStack.reverse()
expArr = expArr.concat(symbolStack);
symbolStack = [];
let numStack: any = [];
for (let i = 0; i < expArr.length; i++) {
if (!isOperator(expArr[i])) numStack.push(expArr[i]);
else {
let res = 0;
let maxv = numStack.length - 1;
if (expArr[i] == "+") {
res = parseFloat(numStack[maxv - 1]) + parseFloat(numStack[maxv]);
}
else if (expArr[i] == "-") {
res = parseFloat(numStack[maxv - 1]) - parseFloat(numStack[maxv]);
}
else if (expArr[i] == "*") {
res = parseFloat(numStack[maxv - 1]) * parseFloat(numStack[maxv]);
}
else if (expArr[i] == "/") {
res = parseFloat(numStack[maxv - 1]) / parseFloat(numStack[maxv]);
}
else { //取余%
res = parseFloat(numStack[maxv - 1]) % parseFloat(numStack[maxv]);
}
numStack.pop();
numStack.pop();
numStack.push(res);
}
}
return numStack[0];
}
function getOperatorPriority(sy) {
if (sy == "+" || sy == "-") {
return 1; //+,-优先级较低为1
}
else if (sy == "*" || sy == "/" || sy == "%") {
return 2; //*,/优先级较高为2
}
else return 0; //如果不为加减乘除符号,则量化为0
}
//判断某个字符是否为数字字符的函数(包含了小数)
function isNumber(char:string):boolean {
return /\d|\./.test(char)
}
//判断某个字符串是否为运算符
function isOperator(n) {
let opts = ['+', '-', '*', '/', '%']
return opts.includes(n)
}
使用
let symbol= ['-', '+', 'right']
let x=10
let y=20
evalMath(x+symbol[0]+y) // -10