为什么使用JavaScript eval函数是个坏主意?
eval函数是一种动态生成代码的强大而简便的方法,那么有哪些警告?
#1楼
我知道这个讨论很古老,但是我真的很喜欢Google的这种方法,并希望与他人分享这种感觉;)
另一件事是,您越了解越多,您就会尝试理解,最后您只是不相信某事是好是坏,只是因为有人这么说:)这是一个非常鼓舞人心的视频 ,帮助我自己进行了更多思考:)好的做法很好,但是请不要轻率地使用它们:)
#2楼
如果您希望用户输入一些逻辑函数并求与与或,则JavaScript eval函数是理想的选择。 我可以接受两个字符串和eval(uate) string1 === string2
等。
#3楼
这是一篇有关eval以及它不是邪恶的好文章: http : //www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
我并不是说您应该精疲力尽,并开始在任何地方使用eval()。 实际上,运行eval()的好用例很少。 绝对存在代码清晰度,可调试性和性能方面的问题,这些问题不容忽视。 但是,当您遇到eval()有意义的情况时,不要害怕使用它。 尝试不要先使用它,但是当适当使用eval()时,不要让任何人吓到您认为代码更脆弱或更不安全。
#4楼
eval()非常强大,可用于执行JS语句或评估表达式。 但是问题不关乎eval()的使用,而只是说一些您用eval()运行的字符串如何受到恶意方的影响。 最后,您将运行恶意代码。 权力伴随着巨大的责任。 因此,明智地使用它就是您正在使用它。 这与eval()函数关系不大,但是本文提供了相当不错的信息: http : //blogs.popart.com/2009/07/javascript-injection-attacks/如果您正在寻找eval()的基础知识在这里查看: https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
#5楼
我不会试图反驳到目前为止所说的任何事情,但是我将提供eval()的这种用法(据我所知)是无法以其他任何方式完成的。 可能还有其他方式对此进行编码,并且可能对其进行优化,但是为了清楚起见,此操作是长期进行的,没有任何花哨的地方,以说明实际上没有任何其他替代方法的eval的使用。 即:动态(或更准确地说)以编程方式创建的对象名称(与值相反)。
//Place this in a common/global JS lib:
var NS = function(namespace){var namespaceParts = String(namespace).split(".");var namespaceToTest = "";for(var i = 0; i < namespaceParts.length; i++){if(i === 0){namespaceToTest = namespaceParts[i];}else{namespaceToTest = namespaceToTest + "." + namespaceParts[i];}if(eval('typeof ' + namespaceToTest) === "undefined"){eval(namespaceToTest + ' = {}');}}return eval(namespace);
}//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){//Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){//Code goes here//this.MyOtherMethod("foo")); // => "foo"return true;
}//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);
编辑:顺便说一句,出于您之前指出的所有安全原因,我不建议您将对象名称基于用户输入。 我无法想象您有什么充分的理由要这么做。 不过,我想指出一点,这不是一个好主意:)
#6楼
JavaScript引擎在编译阶段执行了许多性能优化。 其中一些可以归结为能够在进行词法分析时基本静态地分析代码,并预先确定所有变量和函数声明所在的位置,以便在执行过程中花费较少的精力来解析标识符。
但是,如果引擎在代码中找到一个eval(..),则它实际上必须假定其对标识符位置的所有认识可能都是无效的,因为它无法在词法分析时确切地知道您可能传递给eval(..)的代码。修改词法作用域或您可能要传递给的对象的内容,以创建要查询的新词法作用域。
换句话说,从悲观的意义上讲,如果存在eval(..),它将进行的大多数优化都是毫无意义的,因此它根本不执行任何优化。
这说明了一切。
参考:
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance
#7楼
这并不总是一个坏主意。 以代码生成为例。 我最近写了一个名为Hyperbars的库,该库弥合了Virtual-dom和handlebars之间的鸿沟。 它通过解析车把模板并将其转换为超标 (随后由虚拟域使用)来实现。 超级脚本首先作为字符串生成,然后在返回之前,通过eval()
将其转换为可执行代码。 我发现在这种特殊情况下eval()
与邪恶完全相反。
基本上来自
<div>{{#each names}}<span>{{this}}</span>{{/each}}
</div>
对此
(function (state) {var Runtime = Hyperbars.Runtime;var context = state;return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {return [h('span', {}, [options['@index'], context])]})])
}.bind({}))
在这种情况下, eval()
的性能不是问题,因为您只需要解释一次生成的字符串,然后多次重复使用可执行输出即可。
你可以看到,如果你好奇的代码生成是如何实现的这里 。
#8楼
如果在代码中发现使用eval(),请记住“ eval()是邪恶的”这一口头禅。
此函数采用任意字符串并将其作为JavaScript代码执行。 当相关代码事先已知(在运行时未确定)时,没有理由使用eval()。 如果代码是在运行时动态生成的,那么通常无需使用eval()就有更好的方法实现目标。 例如,仅使用方括号表示法访问动态属性会更好,更简单:
// antipattern
var property = "name";
alert(eval("obj." + property));// preferred
var property = "name";
alert(obj[property]);
使用eval()
也有安全隐患,因为您可能正在执行已被篡改的代码(例如,来自网络的代码)。 在处理来自Ajax请求的JSON响应时,这是常见的反模式。 在这种情况下,最好使用浏览器的内置方法来解析JSON响应,以确保其安全有效。 对于本机不支持JSON.parse()
浏览器,可以使用JSON.org中的库。
同样重要的是要记住,在大多数情况下,将字符串传递给setInterval()
, setTimeout()
和Function()
构造Function()
类似于使用eval()
,因此应避免使用。
在后台,JavaScript仍然必须评估并执行您作为编程代码传递的字符串:
// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);
使用新的Function()构造函数与eval()相似,应谨慎使用。 它可能是一个强大的结构,但经常被滥用。 如果绝对必须使用eval()
,则可以考虑使用new Function()代替。
潜在的好处很小,因为在new Function()中评估的代码将在局部函数范围内运行,因此在评估的代码中用var定义的任何变量都不会自动成为全局变量。
防止自动全局变量的另一种方法是将eval()
调用包装到立即函数中。
#9楼
我要说的是,如果您在浏览器中运行的javascript中使用eval()
并没有关系,*(caveat)
所有现代的浏览器都有一个开发人员控制台,您可以在其中执行任意JavaScript,并且任何半聪明的开发人员都可以查看您的JS源并将所需的任何内容放入开发人员控制台中以完成所需的工作。
*只要您的服务器端点具有对用户提供的值的正确验证和清除,则在客户端javascript中解析和评估的内容无关紧要。
但是,如果您要问是否适合在PHP中使用eval()
,则答案为NO ,除非您将可能传递给eval语句的所有值列入白名单 。
#10楼
垃圾收集
浏览器的垃圾回收不知道是否可以将已评估的代码从内存中删除,因此只能将其保存直到重新加载页面。 如果您的用户不久才出现在您的页面上,也不错,但这对于webapp来说可能是个问题。
这是演示问题的脚本
https://jsfiddle.net/CynderRnAsh/qux1osnw/
document.getElementById("evalLeak").onclick = (e) => {for(let x = 0; x < 100; x++) {eval(x.toString());}
};
与上述代码一样简单的操作会导致存储少量内存,直到应用程序终止。 当逃避的脚本是一个巨大的函数并按间隔调用时,情况更糟。
#11楼
我相信这是因为它可以从字符串执行任何JavaScript函数。 使用它可以使人们更容易地将恶意代码注入到应用程序中。
#12楼
主要是,它很难维护和调试。 就像goto
。 您可以使用它,但是它使发现问题变得更加困难,并且使以后可能需要进行更改的人员变得更加困难。
#13楼
如果传递有效的用户输入,通常这只是一个问题。
#14楼
除非您100%确定要评估的代码来自受信任的源(通常是您自己的应用程序),否则这是使您的系统遭受跨站点脚本攻击的肯定方式。
#15楼
除了在执行用户提交的代码时可能出现的安全问题外,大多数时候,还有一种更好的方法,它不需要每次执行代码都重新解析。 匿名函数或对象属性可以代替eval的大多数用法,并且更加安全,快捷。
#16楼
错误使用eval会使您的代码遭受注入攻击
调试可能会更具挑战性(没有行号等)
评估的代码执行速度较慢(没有机会编译/缓存评估的代码)
编辑:正如@Jeff Walden在评论中指出的那样,今天#3的真实性要低于2008年。但是,尽管可能会缓存一些已编译脚本,但这仅限于未经修改就重复的脚本。 更有可能的情况是您正在评估每次都经过略微修改且因此无法缓存的脚本。 我们只说某些评估代码的执行速度较慢。
#17楼
随着下一代浏览器以某种JavaScript编译器的形式出现,这可能会成为一个更大的问题。 在这些较新的浏览器上,通过Eval执行的代码可能无法像其他JavaScript一样出色地运行。 有人应该做一些分析。
#18楼
我想到两点:
安全性(但是,只要您生成要自己评估的字符串,这可能就不是问题了)
性能:除非要执行的代码未知,否则无法对其进行优化。 (关于javascript和性能,当然是Steve Yegge的介绍 )
#19楼
除非您让eval()动态内容(通过cgi或输入),否则它与页面中所有其他JavaScript一样安全可靠。
#20楼
将用户输入传递给eval()会带来安全风险,但是每次调用eval()都会创建一个新的JavaScript解释器实例。 这可能是资源浪费。
#21楼
这可能会带来安全风险,执行范围不同,效率很低,因为它会为代码执行创建全新的脚本环境。 有关更多信息,请参见此处: eval 。
但是,它非常有用,与审核一起使用可以添加许多良好的功能。
#22楼
这大大降低了您对安全性的信心。
#23楼
除了其他答案外,我认为eval语句无法实现高级最小化。
#24楼
只要您知道使用它的上下文,并不一定很糟。
如果您的应用程序正在使用eval()
从某个JSON创建对象,而该JSON从XMLHttpRequest返回到您自己的站点(由受信任的服务器端代码创建),则可能不是问题。
无论如何,不受信任的客户端JavaScript代码不能做太多事情。 只要您执行eval()
的东西来自合理的来源,就可以了。
#25楼
评估并不总是邪恶的。 有时它是完全合适的。
但是,eval在当前和历史上被不知道自己在做什么的人过度使用。 不幸的是,这包括编写JavaScript教程的人员,在某些情况下,这的确可能带来安全后果-或更常见的是简单的错误。 因此,我们可以做的越多,就对eval提出问号越好。 每次使用eval时,您都需要检查自己在做什么,因为您可能会以更好,更安全,更干净的方式进行操作。
举一个非常典型的例子,设置一个元素的颜色,该元素的ID存储在变量“ potato”中:
eval('document.' + potato + '.style.color = "red"');
如果上面的代码类型的作者对JavaScript对象的工作原理有一定的了解,他们将意识到可以使用方括号代替文字点名,从而避免了eval的需要:
document[potato].style.color = 'red';
...这更容易阅读,而且不存在潜在的错误。
(但是然后,一个/ really /知道自己在做什么的人会说:
document.getElementById(potato).style.color = 'red';
比直接从文档对象中访问DOM元素的狡猾的老技巧更可靠。)
#26楼
要记住的一件事是,您经常可以在其他受限制的环境中使用eval()执行代码-阻止特定JavaScript功能的社交网站有时可能会在eval块中被分解而被愚弄-
eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');
因此,如果您正在运行某些JavaScript代码(否则可能不允许这样做)( Myspace ,我正在查看您...),那么eval()可能是一个有用的技巧。
但是,由于上述所有原因,您不应将其用于拥有完全控制权的自己的代码中-只是没有必要,而且最好放到“棘手的JavaScript hacks”架子上。
为什么使用JavaScript eval函数是个坏主意?相关推荐
- JavaScript eval() 函数,计算某个字符串,并执行其中的的 JavaScript 代码。
JavaScript eval() 函数,计算某个字符串,并执行其中的的 JavaScript 代码. 适合用于计算器的计算,等. 例子: eval("x=10;y=20;document. ...
- JavaScript eval() 函数
定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 Java ...
- JavaScript eval() 函数的用法
定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 返回值 通过计算 string 得到的值(如果有的话). 说明 该方法只接受原始字符串作为参数,如果 st ...
- Javascript eval()函数 基础回顾
如果您想详细了解ev al和JSON请参考以下链接: eval :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Glo ...
- javascript eval函数解析json数据时为什加上圆括号eval((+data+))
原因很简单:因为在js中{}表示一个语句块(代码段),所有加上"()"表示表达式 转载于:https://www.cnblogs.com/lihongchen/p/4270334. ...
- JQuery eval函数
eval函数语法 转载: http://lxbfly.iteye.com/blog/1213734 eval(codes); eval函数参数 codes -- 字符串形式的表达式或语句 eval函数 ...
- js html字符串转对象,js eval函数使用,js对象和字符串互转.
js eval函数使用,js对象和字符串互转. JavaScript eval() 函数 JavaScript 全局函数 定义和用法 eval() 函数计算 JavaScript 字符串,并把它作为 ...
- 深入认识javascript中的eval函数
来源:http://wanyij.blog.51cto.com/46570/43794 发现为本文起一个合适的标题还不是那么容易,呵呵,所以在此先说明下本文的两个目的: (1)介绍javascript ...
- java 动态字符串_Java动态编译执行一串字符串,类似于Javascript里的eval函数
Javascript里的eval函数能动态执行一串js脚本. 那Java里怎么做到呢. 有两种方法: 一种是使用可以执行js脚本的Java类 ScriptEngineManagerpublic sta ...
最新文章
- office插件开发_Visual Studio Code有哪些你常用的插件?
- 基数排序中的LSD方法和MSD方法
- git设置忽略文件和目录
- ubuntu共享文件夹或文件等右下角一把锁的标志【终极解除右下角锁的方法】
- 单片机按键软硬件设计技巧!
- mysql in 按顺序排序_mysql in 排序 也可以按in里面的顺序来排序
- Open3d之彩色点云配准
- Ivy Bridge处理器
- 解决问题--Could not get JDBC Connection
- latex中png、pdf和eps格式的图片文件转换
- Google NIK插件的介绍及使用
- 玛雅日历和2012年12月,whats的新政
- iOS iPad和iPhone开发区别~笔记 03
- 在VS2017中添加WTL窗口
- wamp phpMyAdmin error #1045 - Access denied for user root@locahost Fixed!
- php如何实现快速压缩视频,如何把大视频压缩小 怎么将视频压缩到最小方便储存...
- 数学建模常用算法—灰色预测
- AS使用Viewbinding出现Could not find method buildFeatures() for arguments报错
- 网络规划设计师 视频笔记
- .计算机软件系统包括,计算机软件系统包括什么
热门文章
- View scrolly 正负问题
- 【剑指offer-Java版】43n个骰子的点数
- Android老項目出现javax/xml/bind/JAXBException异常问题解决
- 数值选择器(NumberPicker)的功能与用法
- linux中将文本中的单词换掉的指令_为什么说从PDF中提取文本是一件困难的事?...
- IOS开发笔记9-C语言基础复习
- Java学习笔记11
- lodop打印不显示页码_CAD上明明有图,但是打印的时候不显示怎么办?原来要这样设置...
- CF1146H Satanic Panic
- Java执行字符串中的运算公式