【问题标题】:Execute JavaScript code stored as a string执行存储为字符串的 JavaScript 代码
【发布时间】:2009-06-02 12:54:36
【问题描述】:

如何执行一些作为字符串的 JavaScript?

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    // how do I get a browser to alert('hello')?
}

【问题讨论】:

    标签: javascript


    【解决方案1】:

    使用eval 函数,如:

    eval("my script here");
    

    【讨论】:

    • 小心!这将执行代码,因此要小心你在哪里/如何得到这个字符串。请注意,任何人都可能尝试在您的字符串中插入恶意代码。
    • @divinci 这称为“跨站点脚本”。见这里:en.wikipedia.org/wiki/Cross-site_scripting.
    【解决方案2】:

    您可以使用函数执行它。示例:

    var theInstructions = "alert('Hello World'); var x = 100";
    
    var F=new Function (theInstructions);
    
    return(F());
    

    【讨论】:

    • 但最后 - 这和打电话给var F=function(){eval(theInstructions);};不一样吗?
    • yes and no: with eval 代码也会被执行,而 with Function() 代码直到 F() 才会执行(用例?检查语法错误但不想执行代码)
    • @stefan 真漂亮...new Function("alert('Hello World');")()
    • 我在 try/catch 块中尝试了这个,它运行良好。我现在可以将输入到文本块中的任何 JavaScript 代码传递给我的函数,然后执行它。然后,catch 块可以将来自 JavaScript 引擎的错误消息插入 DOM 元素并显示代码中的任何错误。如果有人想要我写的函数,那么我整理好后,可以在这里发布。
    • @DavidEdwards 如果您仍然拥有它并发布它会很棒。
    【解决方案3】:

    eval function 将评估传递给它的字符串。

    但使用eval can be dangerous,请谨慎使用。

    编辑: annakata 有一个好处——eval 不仅危险,而且很慢。这是因为要评估的代码必须在现场解析,这样会占用一些计算资源。

    【讨论】:

    • 超级危险和缓慢 - 你应该加粗、斜体、下划线和 h1
    • 我怀疑它是否比在页面上的其他任何地方加载 JavaScript 慢,这也必须被解析。如果速度较慢,那是因为它是在不同的范围内完成的,这可能会强制为该范围创建资源。
    • 如果你说eval() 很危险。有没有其他选择?
    • @coobird 我知道这有点晚了,但为什么这么危险?用户可以使用控制台轻松地在您的网站上运行 JavaScript 代码。
    • 如果您的安全性完全依赖于客户端 javascript,那么您已经搞砸了,这与 eval 无关。
    【解决方案4】:

    使用 eval()。

    W3 Schools tour of eval。网站有一些可用的 eval 示例。 The Mozilla documentation covers this in detail.

    您可能会get a lot of warnings 关于安全地使用它。 不允许用户向 eval() 中注入任何东西,因为这是一个巨大的安全问题。

    您还想知道 eval() 有一个不同的scope

    【讨论】:

    • w3fools.com。 W3C 甚至没有任何关于 eval 的说法。如果你想链接到官方的东西,目标ecma-international.org/ecma-262/5.1/#sec-15.1.2.1
    • 我不想“链接到任何官方的东西,我想链接到可读的东西 - 查看 you 链接的内容,它没有解释它是如何使用的,没有例子,没有办法修补,孤立地描述方法。对于初学者来说,这是一个完全不合适的链接。嘿,你不会碰巧是@bjorninge吧?
    • 该规范对eval 的描述比 W3Schools 的那篇文章对我来说更好。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 是具有良好解释和示例的可读性。不,我不是 bjorninge
    • 我同意这不是文档,我同意 mozilla 的页面是一个更好的整体图片。根据反馈稍微调整了我的答案
    • 关于 ecma-international.org 链接,我将其描述为具有 15 分钟以上 JS 经验的每个人都可以阅读和欣赏。非常好。
    【解决方案5】:

    对于使用 node 并且关心eval() 的上下文含义的用户,nodejs 提供vm。它创建了一个 V8 虚拟机,可以在单独的上下文中对代码的执行进行沙箱化处理。

    更进一步的是vm2,它强化了vm,允许虚拟机运行不受信任的代码。

    const vm = require('vm');
    
    const x = 1;
    
    const sandbox = { x: 2 };
    vm.createContext(sandbox); // Contextify the sandbox.
    
    const code = 'x += 40; var y = 17;';
    // `x` and `y` are global variables in the sandboxed environment.
    // Initially, x has the value 2 because that is the value of sandbox.x.
    vm.runInContext(code, sandbox);
    
    console.log(sandbox.x); // 42
    console.log(sandbox.y); // 17
    
    console.log(x); // 1; y is not defined.
    

    【讨论】:

    • 与其说“eval 是邪恶的”并且没有给出任何上下文或解决方案,这实际上试图解决问题。为你 +1
    【解决方案6】:

    试试这个:

      var script = "<script type='text/javascript'> content </script>";
      //using jquery next
      $('body').append(script);//incorporates and executes inmediatelly
    

    就个人而言,我没有测试它,但似乎可以工作。

    【讨论】:

    • 您忘记在脚本中转义关闭 >:var script = "\>";
    • 为什么要转义关闭>?
    【解决方案7】:
    new Function('alert("Hello")')();
    

    我认为这是最好的方法。

    【讨论】:

      【解决方案8】:

      有点像 @Hossein Hajizadeh alerady 所说的,但更详细:

      eval() 有一个替代方案。

      函数setTimeout()被设计为在毫秒间隔后执行某些东西,而要执行的代码恰好被格式化为字符串。

      它会像这样工作:

      ExecuteJavascriptString(); //Just for running it
      
      function ExecuteJavascriptString()
      {
          var s = "alert('hello')";
          setTimeout(s, 1);
      }

      1 表示在执行字符串之前会等待 1 毫秒。

      这可能不是最正确的方法,但它确实有效。

      【讨论】:

      • 当您可以将 0(零)传递给 setTimeout 时,为什么要浪费一毫秒?请注意,无论如何它都会使执行异步。这意味着setTimeout 调用之后的所有代码都将在传递给setTimeout 的代码之前 被调用(即使使用0(零)调用)。
      • ?‍♀️ 只是认为它更好地解释了 setTimeout 的工作原理
      【解决方案9】:

      在许多复杂和混淆的脚本上检查了这一点:

      var js = "alert('Hello, World!');" // put your JS code here
      var oScript = document.createElement("script");
      var oScriptText = document.createTextNode(js);
      oScript.appendChild(oScriptText);
      document.body.appendChild(oScript);
      

      【讨论】:

        【解决方案10】:

        如下使用eval。应谨慎使用 Eval,对“eval is evil”的简单搜索应该会抛出一些指针。

        function ExecuteJavascriptString()
        {
            var s = "alert('hello')";
            eval(s);
        }
        

        【讨论】:

        • 很好的提示关于“eval is evil”的简单搜索谢谢!
        【解决方案11】:

        New Function 和apply() 也可以一起使用

        var a=new Function('alert(1);')
        a.apply(null)
        
        【解决方案12】:

        如果你想在一个特定的命令(即字符串)之后执行 特定的时间 - cmd=你的代码 - InterVal=延迟运行

         function ExecStr(cmd, InterVal) {
            try {
                setTimeout(function () {
                    var F = new Function(cmd);
                    return (F());
                }, InterVal);
            } catch (e) { }
        }
        //sample
        ExecStr("alert(20)",500);
        

        【讨论】:

        • @SteelBrain 添加由 ExecStr("alert(20)",500); 运行的示例;
        • 为什么Val 中的InterVal 大写?
        • InterVal 用作参数,这就是它大写的原因。
        【解决方案13】:
        eval(s);
        

        但是,如果您从用户那里获取数据,这可能会很危险,尽管我认为如果他们自己的浏览器崩溃了,那就是他们的问题。

        【讨论】:

        • 完全正确。 eval 在服务器端很危险。在客户端...不是那么多。用户只需在浏览器地址中输入 javascript:someevilcode 即可。评估就在那里。
        • @EsbenSkovPedersen 这至少在 chrome 中被阻止了,它需要用户操作,而不是 evals 用户代码的网站,例如,这可能让用户在他们不知道的情况下窃取其他用户的帐户只需加载页面。
        • @1j01 公平地说,我的评论已有五年历史了。
        • @EsbenSkovPedersen 这是真的 :)
        【解决方案14】:

        我正在回答类似的问题,并获得了另一个想法,如何在不使用 eval() 的情况下实现这一目标:

        const source = "alert('test')";
        const el = document.createElement("script");
        el.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
        document.head.appendChild(el);
        

        在上面的代码中,您基本上创建了包含脚本的 Blob,以便创建对象 URL(在浏览器内存中表示文件或 Blob 对象)。由于您在 &lt;script&gt; 标记上具有 src 属性,因此脚本的执行方式与从任何其他 URL 加载的方式相同。

        【讨论】:

          【解决方案15】:
          function executeScript(source) {
              var script = document.createElement("script");
              script.onload = script.onerror = function(){ this.remove(); };
              script.src = "data:text/plain;base64," + btoa(source);
              document.body.appendChild(script);
          }
          
          executeScript("alert('Hello, World!');");
          

          【讨论】:

            【解决方案16】:

            不确定这是不是作弊:

            window.say = function(a) { alert(a); };
            
            var a = "say('hello')";
            
            var p = /^([^(]*)\('([^']*)'\).*$/;                 // ["say('hello')","say","hello"]
            
            var fn = window[p.exec(a)[1]];                      // get function reference by name
            
            if( typeof(fn) === "function") 
                fn.apply(null, [p.exec(a)[2]]);                 // call it with params
            

            【讨论】:

              【解决方案17】:

              Stefan's answer的扩展:

              //Executes immediately
              function stringToFunctionAndExecute(str) {
                  let func = new Function(str);
                  return (func()); // <--- note the parenteces
              }
              
              //Executes when called
              function stringToFunctionOnly(str) {
                  let func = new Function(str);
                  return func;
              }
              
              // -^-^-^- Functions -^-^-^- (feel free to copy)
              // -v-v-v- Explanations -v-v-v- (run code to read easier)
              
              console.log('STEP 1, this executes directly when run:')
              let func_A = stringToFunctionAndExecute("console.log('>>> executes immediately <<<')");
              
              console.log("STEP 2, and you can't save it in a variable, calling a() will throw an error, watch:")
              try {
                func_A();    
              } catch (error) {
                console.log('STEP ERROR, see, it failed', error)    
              }
              
              console.log('STEP 3, but this will NOT execute directly AND you can save it for later...')
              let func_B = stringToFunctionOnly("console.log('>>> executes when called <<<')");
              
              console.log("STEP 4, ...as you see, it only run when it's called for, as is done now:")
              func_B();
              
              console.log('STEP 5, TADAAAAA!!')

              【讨论】:

                【解决方案18】:

                eval 应该这样做。

                eval(s);
                

                【讨论】:

                  【解决方案19】:
                  eval(s);
                  

                  但请记住,eval 非常强大且非常不安全。您最好确信您正在执行的脚本是安全的,并且不会被用户更改。

                  【讨论】:

                  • 在 JS 中,用户可以更改所有内容,只需键入“javascript:document.write("Hello World");”进入几乎所有浏览器的地址栏。
                  • 是的,但是你可以通过不使用全局变量、将你的函数隐藏在闭包中等来让他更难。另外,通过避免像瘟疫一样的 eval =)
                  【解决方案20】:

                  可以使用mathjs

                  来自上述链接的片段:

                  // evaluate expressions
                  math.evaluate('sqrt(3^2 + 4^2)')        // 5
                  math.evaluate('sqrt(-4)')               // 2i
                  math.evaluate('2 inch to cm')           // 5.08 cm
                  math.evaluate('cos(45 deg)')            // 0.7071067811865476
                  
                  // provide a scope
                  let scope = {
                      a: 3,
                      b: 4
                  }
                  math.evaluate('a * b', scope)           // 12
                  math.evaluate('c = 2.3 + 4.5', scope)   // 6.8
                  scope.c                                
                  

                  scope 是任何对象。所以如果你将全局作用域传递给evalute函数,你也许可以动态地执行alert()。

                  mathjs 也是比 eval() 更好的选择,因为它在沙箱中运行。

                  用户可能会尝试通过 表达式解析器。 mathjs 的表达式解析器提供了一个沙盒 环境来执行表达式,这应该使这不可能。 虽然可能存在未知的安全漏洞, 所以小心很重要,尤其是在允许服务器端时 执行任意表达式。

                  较新版本的 mathjs 不使用 eval() 或 Function()。

                  解析器主动阻止访问 JavaScript 的内部 eval 和 新功能是安全攻击的主要原因。数学 版本 4 和更高版本不使用 JavaScript 的 eval 底层。 版本 3 和更早版本确实使用 eval 进行编译步骤。这不是 直接是一个安全问题,但会导致更大的可能攻击 表面。

                  【讨论】:

                    【解决方案21】:

                    同时使用 eval 和创建一个新的 Function 来执行 javascript comes with a lot of security risks.

                    const script = document.createElement("script");
                    const stringJquery = '$("#button").on("click", function() {console.log("hit")})';
                    script.text = stringJquery;
                    document.body.appendChild(script);
                    

                    我更喜欢这种方法来执行我收到的字符串形式的 Javascript。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多