在JavaScript中尽量不使用eval

yumo6661个月前 (05-21)技术文章5

前言

在修改一个问题的时候,发现在竟然用eval计算数组的和,不知道当时为什么会这样写(有点不过脑子),不过eval尽量不要使用,在MDN有2个不建议使用eval的建议:

  1. 安全性,eval使用与调用者相同的权限执行代码,如跨站脚本攻击(XSS),恶意脚本注入到页面中,从而控制用户的浏览器.
  2. 性能,eval必须调用JavaScript的解释器,在由解释器转为机器码,任意一个eval的使用都会强制浏览器进行冗长的变量名称查找,以确定变量在机器代码中的位置并设置其值.

如果要使用evel,可以使用Function进行替代,在MDN说Function比eval快,在后面的测试中,Function并没有比eval快很多.

示例代码

function generateRandomArray(len) {
    let arr = [];
    for (let i = 0; i < len; i++) {
        let value = Math.floor(Math.random() * len * 10);
        arr.push(value);
    }
    return arr;
}

function test() {
    let sumArr = [];
    let randomArray = generateRandomArray(16);
    for (var i = 0, len = randomArray.length; i < len; i++) {
        //处理其他的逻辑
        sumArr.push(randomArray[i]);
    }
    let expression = sumArr.join('+');
    let sum = eval(expression); //使用eval计算 '1+2'表达式
    console.log(expression);
    console.log(sum);
}

看一下结果:

先说说test函数中有哪些问题:

1) 使用eval计算表达式

2) 使用sumArr数组,多增加内存的使用,计算数组内值的和,没必要增加一个数组.

不使用evel,可以使用那些方式

1) 最直接的方式,直接在for循环中进行计算

2) 使用JavaScript中reduce函数计算.

3) 使用Function代替eval函数计算.

来测试这几种方式,那个性能比较好.

function generateRandomArray(len) {
    let arr = [];
    for (let i = 0; i < len; i++) {
        let value = Math.floor(Math.random() * len * 10);
        arr.push(value);
    }
    return arr;
}

function evalTest(randomArray, testLen) {
    let sum = 0;
    let sumArray = [];
    console.time('eval ' + testLen);
    for (var i = 0, len = randomArray.length; i < len; i++) {
        sumArray.push(randomArray[i]);
    }
    sum = eval(sumArray.join('+')); //使用eval计算表达式
    console.timeEnd('eval ' + testLen);
    console.error('eval:' + sum);
}

function forTest(randomArray, testLen) {
    let sum = 0;
    console.time('for ' + testLen);
    for (var i = 0, len = randomArray.length; i < len; i++) {
        //最简单直接的方式,直接求和运算
        sum += randomArray[i];    
    }
    console.timeEnd('for ' + testLen);
    console.error('for:' + sum);
}

function readuceTest(randomArray, testLen) {
    let sum = 0;
    console.time('reduce ' + testLen);
    sum = randomArray.reduce((previousValue, currentValue) => {
        return previousValue + currentValue
    }, 0);  //使用reduce
    console.timeEnd('reduce ' + testLen);
    console.error('reduce:' + sum);
}

function functionTest(randomArray, testLen) {
    let sum = 0;
    let sumArray = [];
    console.time('function ' + testLen);
    for (var i = 0, len = randomArray.length; i < len; i++) {
        sumArray.push(randomArray[i]);
    }
    //使用Function
    sum = new Function('"use strict"; return ' + sumArray.join('+') + ';')();
    console.timeEnd('function ' + testLen);
    console.error('function:' + sum);
}

function allTest() {
    var testLenArray = [16, 64, 128];
    for (var i = 0, len = testLenArray.length; i < len; i++) {
        let randomArray = generateRandomArray(testLenArray[i]);
        evalTest(randomArray, testLenArray[i]);
        forTest(randomArray, testLenArray[i]);
        readuceTest(randomArray, testLenArray[i]);
        functionTest(randomArray, testLenArray[i]);
    }
}
allTest();

先看看Edge浏览器执行结果:

然后看看Firefox浏览器的执行结果:

通过测试结果得出:

1) 在循环内,直接求和的方式在数组长度不多的情况,性能最好

2) reduce在数组长度相对多之后,性能比for求值性能好

3) Function在性能上和eval半斤八两

个人能力有限,如果您发现有什么不对,请私信我

如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流

相关文章

python强大但很危险的一个函数eval()

在 Python 中,eval() 是一个强大但危险的函数,用于执行字符串形式的 Python 表达式。以下是深度解析:一、基础用法result = eval(expression, globals=...

「前端开发」eval() 函数认知和学习以及注意事项

一、简单说明简单说几点吧:eval() 函数在 JavaScript 中是一个非常强大的函数,它可以将传入的字符串当作 JavaScript 代码进行执行。然而,需要明确的是,eval() 并不直接支...

干货 | 深度辨析 Python 的 eval() 与 exec()

优质文章,第一时间送达!Python 提供了很多内置的工具函数(Built-in Functions),在最新的 Python 3 官方文档中,它列出了 69 个。大部分函数是我们经常使用的,例如 p...

js中eval() 方法的使用以及一些特殊的使用方式

1、eval方法只能在非严格模式中进行使用,在use strict中是不允许使用这个方法的。2、eval函数接收一个参数s,如果s不是字符串,则直接返回s。否则执行s语句。如果s语句执行结果是一个值,...

php中assert和eval的详细介绍(代码示例)

本篇文章给大家带来的内容是关于php中assert和eval的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。assert 判断一个表达式是否成立。返回true o...

清华团队深度实证:RL 真能让大模型进化吗?能力边界仍被基座“锁死”!

大数据文摘出品强化学习(RL)真的能让大模型获得超越基础模型的新推理能力吗?近日,清华大学LeapLab团队联合上海交大,发布了一篇题为《Does Reinforcement Learning Rea...