2013-12-22 37 views
0

我正在为学生(第二语言使用者,9岁至12岁)转换教程以在离线/内联网环境中访问。因此,我希望他们使用的网站不可用。替代DOM操作中的eval()

我想模仿为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()是一个坏主意。

我可以得到textarea内容弹出在一个div如果我想,但我不能让它在任何地方的脚本弹出...离开我只是eval()。

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

+1

不相信一切你读,尤其是过度概括。 – dandavis

+0

* eval *的**使用**几乎总是不好。 * eval *本身只是一种语言功能,可用于优点或滥用。 – RobG

回答

-1

你可以做

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

此方法不起作用。 'window [“1 + 1”]();'不会产生2。 –

1

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

1

首先,使用eval并不是一个“坏主意”。其次:任何取代eval的东西都会有相同的“缺点”,因为它会执行代码。您必须执行代码才能执行此操作。如果你不想让自己的翻译(至少十倍更糟和更脆弱),你必须坚持评估或类似的东西。

现在它有什么危险?没有别的,但它执行代码的事实。这就像告诉某人一把锤子很危险,因为它很难击中 - 是的,而且它在钉钉时是必要的。当然,锤子可以杀死。

所以,

  1. 使用eval,
  2. ...但消毒它得到的代码(=注意危险表情等)。

您可以限制很多事情对于用户来说,就像每行只有一个指令,只有双引号等,使之更加可控。任何超出限制的内容都将被删除。如果没有危险的东西可以通过输入推动,eval是无害的。

1

选项和替代方案的建议请...或这是一样好,因为它得到?

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

这将使代码在全局范围内评估,因此您的局部变量都不能被触及。它还允许JS引擎更容易地优化本地代码。使用eval()可以禁用优化。


所以使用Function构造,只是通过代码EVAL作为最后一个参数。由于你没有为新函数定义的参数,它将是唯一的参数。

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

然后调用该函数。

f(); 

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


和当然,你可以做到这一切在一个行,如果你只是一次调用它。

new Function(document.getElementById("demoScript").value)(); 
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