【问题标题】:Is this a suitable case in which using dynamic function creation would be justified?这是一个合适的情况,在这种情况下使用动态函数创建是合理的吗?
【发布时间】:2009-01-29 01:36:01
【问题描述】:

我目前正在开发一个教程网站,用于教授 Web 开发的基础知识(HTML、CSS 和 JavaScript,对于初学者)。我想要一个可以深入涵盖各种主题的设置,然后提供一个基本的沙盒环境,用户可以在其中编写代码来解决每个教程部分末尾提出的问题。

例如,如果我在之前的教程中介绍了乘法,并且用户刚刚完成了有关能够返回值的函数的课程,我可能会要求他们提交一个返回两个参数乘积的函数。

这难道不是 完美 实例,其中使用动态函数创建被认为是一个好主意吗?让我们看一个例子。

<script>
function check()
 {
eval('var f = ' + document.getElementById('user_code').value);
if (f(5, 10) == 50)
 {
// user properly wrote a function which
// returned the product of its parameters
 }
 }
</script>

这是一个坏主意吗?如果有,请解释一下。

【问题讨论】:

    标签: javascript dynamic-function


    【解决方案1】:

    这听起来可行。但是,您的环境中最大的挑战可能是错误处理。学生肯定会犯各种错误:

    • 编译时错误,将在eval() 中检测到
    • 运行时错误,将在您调用函数时检测到
    • 无法检测到的运行时错误,例如无限循环或堆栈溢出

    更精细的方法可能会将输入的 Javascript 解析为解析树表示,然后将其与预期的解析树进行比较。如果不匹配,请指出可能出错的地方并让学生再试一次。如果匹配,那么您可以eval() 并调用该函数,知道它会按照您的预期进行。

    在 Javascript 中为 Javascript 实现词法分析器和解析器具有挑战性,但肯定不是不可能的。

    【讨论】:

      【解决方案2】:

      只要您在封闭的环境中操作它就应该可以工作。 Eval 使您面临代码注入攻击,因此我不会将其放在可公开访问的网站上,但如果它完全包含在您的教室中,您应该没问题。

      【讨论】:

        【解决方案3】:

        代码可以工作,但是如果在语法或其他方面都存在错误怎么办?也许使用 try 块来捕获任何错误并将其显示给用户会有所帮助...

        不确定这是否有帮助。

        【讨论】:

          【解决方案4】:

          听起来您想重制Firebug 甚至是IE8 中的新开发者工具。因此,我不得不说从来没有一个有用的案例。更不用说如果这个网站公开了脚本注入的可能性。

          【讨论】:

          • 您正在尝试重新发明轮子。你宁愿我只是说不,因为你想要完成的事情已经完成了吗?
          • 你肯定没有正确阅读我的问题;我明确表示我正在考虑在网站上使用这种方法是有原因的。我到底为什么要寻找一个只支持 Firefox 的工具,它甚至不能做我一开始所询问的事情?
          • 你绝对可以在 Firebug 中编写函数......哦,你也可以在 IE8 中。
          • 最后一件事。 firebug 不只是 FF。
          【解决方案5】:

          在你的情况下,我觉得这并没有什么问题。或者,您可以使用new Function() 来运行代码,首先构建东西然后运行它。理论上,这会将“编译”和执行的阶段分开。但是eval 会先检查代码并抛出错误:

          var usercode = document.getElementById('user_code').value;
          try {
          
            var f = new Function( 'a','b','return (' + usercode + ')(a,b);' );
            if ( f( 5, 10 ) ) {
              // user properly wrote a function which
              // returned the product of its parameters
            }
            else {
              // user wrote code that ran but produced incorrect results
            }
          
          }
          catch ( ex ) {
            // user wrote something really bad
          }
          

          以这种方式做事的问题是抛出的异常可能是无意义的。 "foo;;=bar" 将在括号中报告“缺少 )”错误,而 eval 将引发适当的语法错误。您可以通过(正则表达式)首先从用户代码中获取参数和主体然后构建它来绕过它。但是,这会比eval 更好吗?

          我认为您真正的问题是帮助用户避免隐式全局变量的陷阱。您将如何帮助用户避免编写由于第一次设置全局而仅在第二次运行时才有效的代码?您不需要每次运行都实现一个干净的沙箱吗?我会看看 jsbin.com、firebug 和类似工具是如何处理这些事情的。

          我的感觉是,你现在应该使用eval,如果需要,以后可以将其更改为更复杂的东西。

          【讨论】:

            猜你喜欢
            • 2012-07-04
            • 2012-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-16
            • 1970-01-01
            相关资源
            最近更新 更多