四种方式动态执行JavaScript

function exec(code, key) {
    switch (key) {
        case 1:
            // eval是同步运行
            // 同步,当前作用域
            eval(code);
            break;
        case 2:
            // 异步执行
            // 异步,全局作用域
            setTimeout(code, 0);
            break;
        case 3:
            // 同步,全局作用域
            const script = document.createElement('script');
            script.innerHTML = code;
            document.body.appendChild(script);
            break;
        case 4:
            // 同步,全局作用域
            // let fn = new Function(code);
            // fn();
            new Function(code)();
            break;
        default:
            console.log('出错啦');
            break;
    }
}

exec("console.log('方式一');", 1);
// 方式一
exec("console.log('方式二');", 2);
// 方式二
exec("console.log('方式三');", 3);
// 方式三
exec("console.log('方式四');", 4);
// 方式四

使用Function进行数学运算

function calculateExpression(str) {
    try {
        return new Function('return ' + str)();
    } catch (error) {
        throw new Error(`'${str}' not the correct expression.`);
    }
}

console.log(calculateExpression('2+3*4/2*3'));
// 20
console.log(calculateExpression('(2+3)*4/2*3'));
// 30
console.log(calculateExpression('2+k*4/2'));
// '2+k*4/2' not the correct expression.

解决微信小程序无法使用eval和Function进行计算的问题

/**
 * 
 * @param {String} str 运算表达式
 * @returns 运算结果
 */
function calculateExpression(str) {
    // 运算符栈
    const operators = [];
    // 操作数栈
    const values = [];
    // 定义运算符的优先级
    const precedence = {
        '+': 1,
        '-': 1,
        '*': 2,
        '/': 2
    };

    /**
     * 辅助函数,用于执行运算
     * @param {*} operators 运算符栈
     * @param {*} values 操作数栈
     */
    function applyOperator(operators, values) {
        const operator = operators.pop();
        const b = values.pop();
        const a = values.pop();

        switch (operator) {
            case '+':
                values.push(a + b);
                break;
            case '-':
                values.push(a - b);
                break;
            case '*':
                values.push(a * b);
                break;
            case '/':
                values.push(a / b);
                break;
            default:
                console.log('出错啦');
                break;
        }
    }

    for (let i = 0; i < str.length; i++) {
        const char = str[i];

        // 如果是数字,解析整个数字
        if (!isNaN(char)) {
            let num = parseFloat(char);

            while (i + 1 < str.length && !isNaN(str[i + 1])) {
                num = num * 10 + parseFloat(str[i + 1]);
                i++;
            }

            values.push(num);
        } else if (char === '(') {
            // 如果是左括号,将其推入运算符栈
            operators.push(char);
        } else if (char === ')') {
            // 如果是右括号,将栈顶运算符应用于运算数,直到遇到左括号为止
            while (
                operators.length > 0 &&
                operators[operators.length - 1] !== '('
            ) applyOperator(operators, values);

            // 弹出左括号
            operators.pop();
        } else if (char in precedence) {
            // 如果是运算符
            while (
                operators.length > 0 &&
                precedence[char] <= precedence[operators[operators.length - 1]]
            ) applyOperator(operators, values);

            operators.push(char);
        }
    }

    // 处理剩余的运算符
    while (operators.length > 0) applyOperator(operators, values);

    // 最终结果位于操作数栈的顶部
    return values[0];
}

console.log(calculateExpression('6+3*2-(10-8)+6/3+3'));
// 15
console.log(calculateExpression('(6+3)*2-10-(8+1)/3+3'));
// 8
console.log(calculateExpression('6+3*2-10-8+6/3+3'));
// -1

eval

W3SCHOOL

eval()函数计算或执行参数。
如果参数是表达式,则eval()计算表达式。如果参数是一个或多个JavaScript语句,则eval()执行这些语句。


MDN

eval()函数会将传入的字符串当做JavaScript代码进行执行。
一个表示JavaScript表达式、语句或一系列语句的字符串。表达式可以包含变量与已存在对象的属性。
返回字符串中代码的返回值。如果返回值为空,则返回undefined
eval()是全局对象的一个函数属性。
eval()的参数是一个字符串。如果字符串表示的是表达式,eval()会对表达式进行求值。如果参数表示一个或多个JavaScript语句,那么eval()就会执行这些语句。不需要用eval()来执行一个算术表达式:因为JavaScript可以自动为算术表达式求值。
如果你以字符串的形式构造了算术表达式,那么可以在后面用eval()对它求值。例如,假设你有一个变量x,你可以通过将表达式的字符串值(例如3 * x + 2)赋值给一个变量,然后在你的代码后面的其他地方调用eval(),来推迟涉及x 的表达式的求值。
如果eval()的参数不是字符串, eval()会将参数原封不动地返回。在下面的例子中,String构造器被指定,而eval()返回了String对象而不是执行字符串。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐