领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

在JavaScript中尽量不使用eval(javascript不运行)

nixiaole 2024-11-17 00:23:52 知识剖析 24 ℃

前言

在修改一个问题的时候,发现在竟然用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半斤八两

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

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

Tags:

最近发表
标签列表