eval is evil!

2023-10-27 21:08
文章标签 eval evil

本文主要是介绍eval is evil!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://www.guhaodi.com/2014/06/29/eval-is-evil/


eval 函数传递一个字符串给 JavaScript 编译器,并且执行其结果.

上面是 JavaScript eval() 函数的定义.语法如下:

eval( string )
用法说明:
  1.  eval() 传递一个包含一个或者多个表达式的字符串, eval() 会调用 JavaScript 编译器,计算并返回表达式的值.
  2. 不用给 eval() 传递一个只包含算术表达式的字符串,因为 JavaScript 会自动计算算术表达式.
  3. 如果 evla() 的参数不是一个字符串,那么,函数不会对参数做任何改变,并且原封不动地返回它.

从上面的介绍看,貌似 eval() 的功能还蛮强大的,它能执行任何传入的 JavaScript 表达式!
那么,为什么大家都建议代码里不要使用 eval() ,甚至不适用它都已经成为一个标准(JSLint中不允许出现eval())了.
主要有下面两个原因:

  1. 安全性太差.尽管 eval() 功能很强大,但恰恰因为它能执行传入的 JavaScript 表达式,并且用户通常能使用第三方插件找到你的代码中什么地方调用了 eval() ,这样就极大增加了你被攻击的可能性.
  2. 性能低. eval() 在执行的时候需要调用 JavaScript 编辑器,这会影响程序的性能.JSON.parse vs eval 解析 JSON 的性能对比

基于以上原因, eval() 并不受开发者欢迎.甚至,国外的 JavaScript 大师 Douglas Crockford(JSON 和 JSLint 都是他提出和创建的) 在他的畅销书 JavaScript: The Good Parts(JavaScript 语言精粹)中明确把 eval() 列为 JavaScript 语言中的糟粕…而且在他的编程规范里禁用 eval() .

那么,既然我们要尽量不使用 eval() ,又有哪些方式可以代替它呢?
可以针对 eval() 常用的情形给出下面两个方法:

1. 解析 JSON 的时候

我以前在处理一个 JSON 字符串的时候,如果要把它解析成一个对象,通常会使用 eval(‘(‘ + jsonStr + ‘)’) 的方式解析.
在了解到 eval() 的可怕后,开始改用 JSON.parse (对应的,还有 JSON.stringify 方法用来解析成JSON字符串)的方法.

JSON.parse 的优点:

  1. 只是把 JSON 字符串解析成对象,不执行表达式,没有像 eval() 那样的安全性问题.
  2. 不调用 JavaScript 编译器,性能完爆 eval()

JSON.parse 的缺点: 只有主流浏览器支持原生 JSON 对象,老的,过时的浏览器没有这个方法.

所以,要想在解析 JSON 的时候,用 JSON.parse 完全取代 eval() ,你必须解决浏览器支持的问题.

Note: 事实上, JSON.parse 是基于 Douglas Crockford 对 JSON 的安全解析方法.JSON.parse 的方法中也使用了 eval(),只不过在使用 eval() 之前,验证了传入 eval() 的字符串是一个合法,安全的字符串,这使得 JSON.parse 能够安全解析 JSON.

为了解决这个问题,推荐你直接引用 Douglas Crockford 在 GitHub 上分享的解决方案,选一个作为你的代码的依赖文件.
或者,也可以自己写一个模拟的 JSON 对象,一个 polyfill:

if (!window.JSON) {window.JSON = {parse: function (sJSON) { return eval("(" + sJSON + ")"); },stringify: function (vContent) {if (vContent instanceof Object) {var sOutput = "";if (vContent.constructor === Array) {for (var nId = 0; nId < vContent.length; sOutput += this.stringify(vContent[nId]) + ",", nId++);return "[" + sOutput.substr(0, sOutput.length - 1) + "]";}if (vContent.toString !== Object.prototype.toString) { return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\"";}for (var sProp in vContent) { sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringify(vContent[sProp]) + ",";}return "{" + sOutput.substr(0, sOutput.length - 1) + "}";}return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent);}};
}

上面这段代码是从这里搬运来的.只要把它放在你代码的最前面就好了.
可惜的是,这段代码还是使用了 eval() ,而且没有对传入的字符串加任何安全验证.效果跟直接使用 eval() 是一样的.
再或者,你如果放弃治疗的话,还可以这样…

if(window.JSON){// 用 JSON.parse
}else{// 用 eval()
}
2. 使用类似 eval() 的方法的时候

JavaScript 中还有其他函数,比如 Function()构造函数, setTimeout() 和 setInterval() 也跟 eval() 一样会执行字符串中的表达式.
比如:

setTimeout('window.location.reload()',1000); // 1秒后刷新页面

上面的代码中 setTimeout() 执行了字符串中的代码.实际上跟 eval() 是一样的.
为了解决这个问题,可以用函数来代替字符串传入 setTimeout() :

setTimeout(function(){window.location.reload(); // 同样能在1秒后刷新页面
},1000);

总结

eval() 低效又不安全,能不用的话,尽量就别用它吧~改成用上面的方式取代它.


这篇关于eval is evil!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/288387

相关文章

UMI复现代码运行逻辑全流程(一)——eval_real.py(尚在更新)

一、文件夹功能解析 全文件夹如下 其中,核心文件作用为: diffusion_policy:扩散策略核心文件夹,包含了众多模型及基础库 example:标定及配置文件 scripts/scripts_real:测试脚本文件,区别在于前者倾向于单体运行,后者为整体运行 scripts_slam_pipeline:orb_slam3运行全部文件 umi:核心交互文件夹,作用在于构建真

python eval报错 SyntaxError: invalid token

a = eval(startTime)   File "<string>", line 1     2019-01-02 11:00:00               ^ SyntaxError: invalid token startTime = '2019-01-02 11:00:00'a = eval(startTime) 具体内容如上: 后来发现,在eval中的

Shell编程:文本处理器(cut、split、paste、eval 命令)

文章目录 文本处理器 2cut 命令-快速裁剪语法格式常用选项示例 split 命令-文件拆分语法格式常用选项示例 paste 命令-文件合并语法格式常用选项示例 eval 命令-变量扫描器工作原理示例 文本处理器 2 本章讲解 grep、sort、uniq、tr、cut、split、paste 命令等。这些文本处理器通常用于数据过滤、转换、清理、格式化和提取等操作,

深度学习01:pytorch中model eval和torch no_grad()的区别

公众号:数据挖掘与机器学习笔记 主要区别如下: model.eval()会通知所有的网络层目前处于评估模式(eval mode),因此,batchnorm或者dropout会以评估模式工作而不是训练模式。 在train模式下,dropout网络层会按照设定的参数p设置保留激活单元的概率(保留概率=p); batchnorm层会继续计算数据的mean和var等参数并更新。 在val模式下,dro

GD - GD32350R_EVAL - PWM实验和验证1

文章目录 GD - GD32350R_EVAL - PWM实验和验证1概述笔记实验设计实验环境GD32350R_EVAL 的硬件连接修改程序配置 - 只产生PWM波,不要CMP清除波形TIMER0时钟设置TIMER0的PWM设置参数设置main()中PWM波形的开启代码示波器测量结果如果要产生4KHZ的PWM需要设置怎样的参数?尝试1 - 算一下时钟设置参数尝试1 - 产生代码,编译,验证错

[论文笔记] eval-big-refactor lm_eval 每两个任务使用一个gpu,并保证端口未被使用

1.5B在eval时候两个任务一个gpu是可以的。 7B+在eval belebele时会OOM,所以分配时脚本不同。 eval_fast.py: import subprocessimport argparseimport osimport socket# 参数列表task_name_list = ["flores_mt_en_to_id","flores_mt_en_to_vi"

L-Eval:一个60k左右长文评测数据集

前言 L-Eval是复旦大学邱锡鹏老师团队在 2023 年 7 月左右发布的一个标准化的长文本语言模型(LCLMs)评估数据集,包含20个子任务、411篇长文档、平均长度为7217个单词,超过2000个人工标记的QA对。它分为封闭型任务和开放型任务,涵盖了法律、金融、学校讲座、长对话、新闻、长篇小说和会议等多个领域,旨在通过不同的评价方法,如长度指令增强(LIE)评价和LLM裁判,来准确反映

[论文笔记] lm_eval 每两个任务使用一个gpu,并保证端口未被使用

1.5B在eval时候两个任务一个gpu是可以的。 7B+在eval belebele时会OOM。 eval_fast.py: import subprocessimport argparseimport os# 参数列表task_name_list = ["flores_mt_en_to_id","flores_mt_en_to_vi","flores_mt_en_to_th","f

model.eval()和torch.no_grad()的区别

model.eval() model.eval()是PyTorch中模型的一个方法,用于设置模型为评估模式。在评估模式下,模型的所有层都将正常运行,但不会进行反向传播(backpropagation)和参数更新。此外,某些层的行为也会发生改变,如Dropout层将停止dropout,BatchNorm层将使用训练时得到的全局统计数据而不是评估数据集中的批统计数据。 torch.no_grad()

json--eval--VM1423:3 Uncaught SyntaxError: Invalid or unexpected token

VM1423:3 Uncaught SyntaxError: Invalid or unexpected token     感觉几天没写了。今天遇到个问题,Java后台返回json格式的数据,但是在用eval转换的时候 报错 js报错,Uncaught SyntaxError: Unexpected token }不知道哪里错,求解答! function processRespo