我正在制作一个小游戏,部分内容我想要一个非常简单的自定义编程语言.如果用户输入代码,例如变量“helloWorld”= 5,则“解释器”会将变量更改为var并将引号删除为普通
JavaScript.
我该如何运行该代码?我读过有关eval()的内容,但我也读过它很慢,不应该使用它.我已经研究了使用词法分析器,解析器和标记器创建编程语言,但我并不打算创建一些深入的东西.
对方向的任何帮助都会很棒.
解决方法
我假设您不需要“如何编写该代码?”的帮助,但是如何执行用户脚本.
关于eval:
> eval慢吗?是.缓慢有多慢?如果一个脚本在10ms内运行并且在20ms内运行,那么对你和你的应用程序来说这是一个问题吗?
>用户可以搞砸eval吗?是!他们可以重新分配函数,全局等.他们可能会意外地破坏页面.
>危险吗?是!您可能容易受到XSS攻击.你有任何敏感数据吗?您的应用程序是否有服务器端?如果没有,我认为eval还可以.
以下是来自不同SO问题的更多信息:
> @L_502_1@
> JS eval security issue
关于防止全球重新分配的想法
将脚本包装在IIFE中!像这样包装脚本:
(function(){ // user script goes here. This will cause it to be in it's own scope! })();
Javascript具有函数范围,因此这将保护全局空间免于填充用户变量和函数.用户仍然会恶意影响全局变量,如下所示:
(function(){Array.isArray = function() { return 2;};})() Array.isArray([]); // returns 2
更多关于eval的速度.一个真实的例子:
#!/bin/env node // Be careful running this. You don't want to melt your cpu. Try 100,000 first. console.time("no-eval"); for (var i = 0; i < 10000000; i++) { Math.sqrt(i); } console.timeEnd("no-eval"); console.time("big-eval"); eval("for (var i = 0; i < 10000000; i++) { Math.sqrt(i); }"); console.timeEnd("big-eval"); console.time("evil-eval"); for (var i = 0; i < 10000000; i++) { eval("Math.sqrt(i);"); } console.timeEnd("evil-eval");
输出:
no-eval: 272ms big-eval: 294ms evil-eval: 1945ms
正如你所看到的,’big-eval’有点慢.您可能会执行big-eval,一次运行用户脚本的所有行. ‘evil-eval’慢得多,因为js引擎运行了10,000,000次eval!