繁体   English   中英

为什么脚本不执行?

[英]Why didn't the script execute?

我正在尝试制作一个使用AJAX刷新其内容,样式和脚本的Web应用程序,因此该网站无需重新加载页面即可更新所有内容。

所以发生的事情是,我首先获取页面,并且在加载页面时,我使用ajax向服务器发出请求并获取html内容,然后再次请求获取样式,最后再次请求获取脚本并将其放入脚本标签

<script> //The script goes here </script>

然后,我将script标签放在html内容的末尾,并用内容完全更新正文

<body>
  The HTML content goes here
  <script> //and here is the script </script>
</body>

请求成功且内容已加载,因此样式和样式以及当我使用浏览器检查器工具时,都可以看到脚本标签中加载的脚本,但脚本未执行。

这是问题的概述,您可以在这里查看代码https://codepen.io/Yousef-Essam/project/editor/ZJGxea

app.js提供index.html文件,然后索引文件获取script.js文件,该文件使用ajax发送两个请求以获取content.html文件和content.js文件,并将link标签的href属性设置为style文件。 然后将content.js文件放入带有新内容的脚本标签中。 尽管加载了content.html和样式文件,并且脚本已加载到script标记中,但脚本未执行。

为什么会发生这种情况,我该如何解决?

--Update--

问题可能出在使用innerHTML上,但是为什么不真正起作用。

另外,我认为eval可能是一个解决方案,但由于不建议使用eval,因此我希望有一个更好的解决方案

这太长了,无法发布为评论,因此我将其作为答案发布。

您正确地注意到:

我认为eval可能是一个解决方案,但由于不建议使用eval,因此我希望有一个更好的解决方案

实际上,eval在任何语言中都是有问题的,因为它本质上允许正在运行的程序将字符串视为代码。 这样做的最大问题是,这为代码注入打开了大门(用外行的术语:黑客攻击)。 但是,此建议更多是理论建议,而不是有关使用什么功能的建议。

那么,该建议对eval意味着什么?

Eval是任何允许将字符串解释为代码的函数或机制。 不同的语言具有不同的功能或特性,可以进行eval 例如,某些语言允许递归字符串插值。 一些语言具有称为interp()的函数,该函数会生成一个子解释器。 有些语言从字面上讲有一个称为eval()的函数。

JavaScript具有四种评估机制:

  1. 使用eval()函数。

    • 传递给eval()任何字符串均视为代码。
  2. 设置脚本标签的src属性

    • 假设src属性的值是要下载的javascript文件
    • 这可以在文字代码(HTML本身的实际代码)或动态生成的脚本标记(在javascript中创建脚本元素并将其设置为src属性)中使用
  3. 脚本标签的正文

    • 脚本标签内的任何文本均视为代码
    • 这仅适用于文字代码。 如您innerHTML ,禁止使用innerHTML设置脚本主体(自Netscape 4-第一个使用javascript的浏览器以来,此设置已被禁止)
  4. javascript: URI协议

    • :之后的所有内容均视为代码
    • 仅在用户单击链接时有效

因此,您想要做的是执行eval 无论您是否使用eval函数都无所谓,您仍在尝试使用innerHTML进行eval (尽管它不起作用)

因此,如果所有内容都是eval ,是否有一种在页面上运行javascript的安全方法?

有-至少对于现代浏览器而言。

现代浏览器实现了一种称为子资源完整性的功能。 不幸的是,在编写此答案时,Edge不支持它。 基本上,您可以计算js文件的哈希值(例如sha1),并在script标签中对其进行声明,以便浏览器可以确认js文件未被篡改。 以下是一个示例:

<script src="https://cdn.example.com/script.js"
 integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"></script>

你这个偏执狂吗?

这取决于。 eval问题对您可能真的很重要。 如果是这样,从设置了子资源完整性的外部源加载javascript 是执行javascript的唯一安全方法

但并非每个人都如此偏执。 到目前为止,我们通常在没有此功能的情况下做得很好。 以下是一些经验法则,无论您使用script标记还是调用eval() ,它们都可以缓解代码泄漏:

  1. 始终确保您仅执行静态javascript代码。 不要尝试从字符串构造代码。

  2. 如果必须从字符串构造代码(例如,使用模板语言(如Handlebars)或使用捆绑程序(如Webpack或Browserify)),则切勿在代码中包含任何用户生成的内容。 您仍然可以通过发出ajax请求而不是将其包含在代码中来加载内容。

  3. 如果必须在代码中包含用户生成的内容,请确保对内容进行清理。 有几种普遍接受的策略,例如禁止使用特殊字符(如<>"或转义特殊字符。甚至还有库都可以为您做到这一点)。

基本上,我们要避免的情况是用户输入他们的名字为John"; console.log("gotcha");" 以及能够执行代码的方式。

HTML规范不允许解析使用innerHTML在页面加载后动态添加为HTML标签的SCRIPT元素(按照生活标准中text属性描述下的注释 )。

因此,在不使用eval来解析脚本的情况下,类似问题的答案在一次简单的搜索中并不明显-尽管它们可能存在,但我只看到了场外展示的替代技术。

这是一个不使用eval的动态加载器。 因为加载脚本是异步的,所以它使用( err, data )类型的回调函数来指示何时可以调用脚本。

function loadScript( url, callback) {
    var el = document.createElement("SCRIPT");
    el.type = "text/javascript";
    function finish( err) {
        callback( err, err ? false : true);
    }
    el.onerror = finish;
    if( el.readyState){  // <= IE 10
        el.onreadystatechange = function(){
            if( this.readyState == "complete"){
                finish( null);
            }
        };
    }
    else { 
        el.onload = function() { finish(null) };
    }
    el.setAttribute("async", true);
    el.src = url;
    document.getElementsByTagName("HEAD")[0].appendChild( el);
} 

// example call to load jQuery 3.2.1         

loadScript( "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js",
   function (err, ok) {
       if( err) {
           console.log( "loading failed: " + err);
        }
        else {
         console.log( "loading success");
        }
    }
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM