在DOM操作中替代eval()

时间:2013-12-22 23:29:05

标签: javascript html5 eval

我正在为学生(第二语言,9到12岁)转换教程,以便在离线/内联网环境中进行访问。因此,我希望他们使用的网站不可用。

我正在尝试模仿用于帮助JavaScript / HTML5 Canvas的“改变代码”风格的教程。

这有效:

<canvas id="myCanvas" height="400px" width="400px"></canvas>
<script>
function update(){
   eval(document.getElementById('demoScript').value);
}

var ctx = document.getElementById("myCanvas").getContext("2d");

</script>
<textarea id="demoScript">
ctx.fillRect(100,100,50,50);
</textarea>
<input type="button" value="update" onClick="update()">

...但我读过的所有内容都说eval()是一个坏主意。

如果我愿意的话,我可以在div中弹出textarea内容,但我无法在任何地方弹出一个脚本...只留下eval()。

替代方案的选项和建议请......或者这是最好的吗?

5 个答案:

答案 0 :(得分:1)

这是eval的可接受用途,因为在最坏的情况下,学生会以无限循环锁定自己的浏览器。

答案 1 :(得分:1)

首先,使用eval并不是一个“坏主意”。 第二:替换eval的任何东西都会有相同的“缺点”,因为它执行代码。您必须执行代码才能执行此操作。如果你不想制作自己的翻译(至少十倍以上,更容易受到攻击),你必须坚持使用eval或类似的东西。

现在有什么危险?除此之外,它执行代码的事实。这就像告诉别人锤子是危险的,因为它很难 - 是的,而且当它被钉住东西时它是必要的。当然,锤子可以杀死。

所以,

  1. 使用eval,
  2. ...但要清理它得到的代码(=注意危险的表达等)。
  3. 您可以为用户限制很多内容,例如每行只有一条指令,只有双引号等,以使其更易于控制。任何超出限制的内容都将被删除。如果没有危险的东西可以通过输入推动,eval是无害的。

答案 2 :(得分:1)

  

替代方案的选项和建议请......或者这是最好的吗?

我建议使用Function构造函数而不是eval。虽然在你的简单例子中它可能没有太大的区别,但在其他情况下可能会有所不同。

这将使代码在全局范围内进行评估,因此无法触及任何局部变量。它还允许JS引擎更轻松地优化本地代码。使用eval()可以禁用优化。


因此,要使用Function构造函数,只需将代码作为最后一个参数传递给eval。由于没有为新函数定义的参数,因此它将是唯一的参数。

var f = new Function("return "  + document.getElementById("demoScript").value);

然后调用该函数。

f();

请注意,我将return语句连接到提供的代码中。如果您不关心从调用的代码中获取返回值,则不需要这样做,如果它可能会干扰提供的代码,则应将其删除。


当然,如果你只想调用一次,你可以在一行中完成这一切。

new Function(document.getElementById("demoScript").value)();

答案 3 :(得分:0)

您可以从textarea获取值字符串,拆分,验证并手动运行 对于这样的演示,在给出ctx的情况下,这样的事情应该起作用

var ctx = document.getElementById("myCanvas").getContext("2d");

function update(){
    var val = document.getElementById('demoScript').value,
        fn  = val.match(/\.(.*?)\(/),
        arg = val.match(/\((.*?)\)/);

    if (fn && fn.length > 0) {
        if (arg && arg.length > 0) {
            var args = arg[1].indexOf(',') != -1 ? arg[1].split(',') : [arg[1]];
            ctx[fn[1]].apply(ctx, args);
        }else{
            ctx[fn[1]]();
        }
    }
}

FIDDLE

答案 4 :(得分:-1)

你可以做到

var fn = document.getElementById("demoScript").value;
window[fn]();