【问题标题】:What happens if you use a <script> tag with the same "src" attribute multiple times within a single HTML document?如果在一个 HTML 文档中多次使用具有相同“src”属性的 <script> 标签会发生什么?
【发布时间】:2009-10-07 19:37:21
【问题描述】:

虽然我几乎可以肯定这个问题的答案是特定于浏览器的,但是否有任何浏览器定义了使用多个 标签并具有相同 src 属性时的行为?

比如……

<script src="../js/foo.js"></script>
...

<!-- what happens here? -->
<script src="../js/foo.js"></script>

我首先提出这个问题的原因是,在我的特殊情况下,我在使用 JQuery 的 ASP.NET MVC 应用程序中使用部分视图。 JQuery JS 文件都通过脚本标签包含在主模板文件中。我更愿意将脚本标签添加到部分视图文件中,以便在主模板上下文之外使用它们时,它们将自动包含所有必要的 JS 文件,而不是依赖另一个视图或模板来包含它们。但是,我当然不想导致 JS 文件必须多次传输到客户端,或者任何其他可能对用户体验产生负面影响的副作用。

我现在的想法是,如果不是全部的话,大多数主流浏览器(FF、Safari、IE、Opera)都会在第一次使用 JS 文件时缓存它,然后浏览器将在后续的脚本标签上使用缓存的副本(如果可用且尚未过期)。但是,缓存行为通常可以通过浏览器配置进行更改,因此依赖任何类型的缓存行为似乎都不太“安全”。

我是否只需要接受这样一个事实,即我的部分视图将依赖于其他模板或视图,包括相应的 JS 文件?

【问题讨论】:

    标签: javascript html asp.net-mvc


    【解决方案1】:

    即使它们被缓存,您也可能会遇到问题,因为相同的代码将被执行两次。至少,这将导致浏览器花费更多的时间。而且它可能会导致错误,因为大多数 JavaScript 代码并不是为了执行两次而编写的。例如,它可能会附加相同的事件处理程序两次。

    【讨论】:

    • +1 一些库受到双重包含的保护,但据我所知,jQuery 没有。不要包含两次。当库被实例化两次时,您可能会出现异常行为。
    • 代码在被调用时被执行。您的意思是说它将被解释两次,这是完全不同的,并且产生的问题与您说明的不同。
    • @austin 代码在加载时会被解释和执行,这和 JS 完全一样。例如,function foo() { } 是一行代码,执行时会创建一个名为 foo 的新全局变量并将函数体的值分配给它。 JW 说这是有问题的,因为它会重复两次。
    • 正确——当你加载一个脚本标签时,解释和执行都会发生。请记住,许多 JS 文件不仅仅是定义函数;其中一些也调用函数,或执行其他操作。
    【解决方案2】:

    不要直接在您的部分输出脚本标签。创建一种机制来注册脚本文件以供以后包含。该机制可以只负责包含一次文件。

    【讨论】:

    • 我喜欢这个主意。您可以使用可以调用的方法创建一个帮助程序,例如 IncludeScript("../js/foo.js"),并让该方法跟踪当前请求已包含哪些脚本。唯一的“技巧”是将数据存储在请求的范围内,以便在视图、模板和部分之间共享有关哪些脚本已包含的信息。我不太确定如何在 ASP.NET MVC 中执行此操作,但我确信它是可行的并且希望相当简单
    • 为了跟进前面的评论,ASP.NET MVC 提供了一些用于存储请求范围数据的选项。一种选择是 ViewData 字典对象,它可以作为视图、部分、模板或 HtmlHelper 扩展方法的属性直接使用。另一个选项是 HttpRequest/HttpRequestBase 的 Items 属性。在这两种情况下,存储在这些集合中的数据将在请求的整个生命周期内保持不变,并且可供请求期间使用的所有视图、部分、模板和 HtmlHelper 扩展方法使用。
    • 你不需要自己动手,你可以用(例如)Page.ClientScript.RegisterClientScriptInclude("jQuery", &lt;jQuery path&gt;);
    【解决方案3】:

    FF 3.5x,Chrome 4x 只包含一次。

    :) IE 8 有两个副本(在“开发者工具”>“脚本”选项卡中查看有两个 jquery-1.3.2.min.js 条目)

    【讨论】:

      【解决方案4】:

      发生的情况是,JavaScript 在下载的那一刻就被输入解释器。在命名空间冲突的情况下,只有给定范围的变量名才能继续执行。通常,这最后唯一的过程可以防止由于覆盖较早输入解释器的函数而出现问题。问题是一个函数定义了变量范围,这些变量可能是其他函数,然后引入变量的其他命名空间范围。这是一个问题,因为如果函数共享相同的名称值并包含不同的变量定义,那么即使在该函数被覆盖后,来自函数馈送到解释器的变量也可能会提前存活,这可能会导致预期的命名空间冲突。

      如果完全相同的文件被包含两次应该没有问题。当包含同一文件的不同版本或包含具有相同函数名称的不同文件时,会出现此问题。两次包含同一个文件可能意味着多次传输,这是对带宽的浪费。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-27
        • 1970-01-01
        • 2014-06-21
        • 2017-07-11
        • 1970-01-01
        • 2020-05-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多