运行动态Javascript代码

use*_*714 8 javascript interpreter dynamic

我正在制作一个小游戏,其中一部分我想要一个非常简单的自定义编程语言.如果用户输入代码,例如variable "helloWorld" = 5"解释器"会将变量更改为var并将引号删除为普通JavaScript.

我该如何运行该代码?我已经读到了eval(),但我也读过它很慢,不应该使用.我已经研究了使用词法分析器,解析器和标记器创建编程语言,但我并不打算创建一些深入的东西.

对方向的任何帮助都会很棒.

Jes*_*ess 8

我假设您不需要"如何编写该代码?"的帮助,但是如何执行用户脚本.

关于eval:

  1. eval慢吗?是.缓慢有多慢?如果一个脚本在10ms内运行并且在20ms内运行,那么对你和你的应用程序来说这是一个问题吗?
  2. 用户可以搞砸eval吗?是! 他们可以重新分配函数,全局等.他们可能会意外地破坏页面.
  3. 危险吗?是! 您可能容易受到XSS攻击.你有任何敏感数据吗?您的应用程序是否有服务器端?如果没有,我认为没问题eval.

以下是来自不同SO问题的更多信息:

关于防止全球重新分配的想法

将脚本包装在IIFE中!像这样包装脚本:

(function(){
// user script goes here.  This will cause it to be in it's own scope!
})();
Run Code Online (Sandbox Code Playgroud)

Javascript具有函数范围,因此这将保护全局空间不被用户变量和函数填充.用户仍然可能恶意影响全局变量,如下所示:

(function(){Array.isArray = function() { return 2;};})()
Array.isArray([]);
// returns 2    
Run Code Online (Sandbox Code Playgroud)

更多关于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");
Run Code Online (Sandbox Code Playgroud)

输出:

no-eval: 272ms
big-eval: 294ms
evil-eval: 1945ms
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,'big-eval'有点慢.您可能会执行big-eval,一次运行用户脚本的所有行.'evil-eval'慢得多,因为js引擎运行了10,000,000次eval!:)


dee*_* zg 0

你的语法可能会得到一些改进,但想法是这样的......

首先,创建函数:

function variable(name, value){
window[name] = value;
}
Run Code Online (Sandbox Code Playgroud)

下一步是解析用户输入(这就是语法改进可以发挥作用的地方)。在您的示例中,您可以完全去掉引号,然后首先将字符串除以“=”,然后用空格留下部分。你得到 3 个元素,分别代表: 1) 函数名称 2) 变量名称 3) 变量值

然后,你调用这样的函数:

window[functionName](variableName, variableValie);
Run Code Online (Sandbox Code Playgroud)