两次包含相同的JavaScript库有什么危险?

Eri*_*Red 43 javascript javascript-framework

我正在使用的其中一个webapp由许多部分HTML文件组成.如果partial需要一个JavaScript库,例如YUI,则YUI库包含在partial中.

当部分在运行时组合时,生成的HTML通常会多次包含YUI库.

<html>
... 
<script type="text/javascript" src="/js/yahoo/yahoo-min.js"></script>
... 
<script type="text/javascript" src="/js/yahoo/yahoo-min.js"></script>
... 
<script type="text/javascript" src="/js/yahoo/yahoo-min.js"></script>
...
</html>
Run Code Online (Sandbox Code Playgroud)

我已经看过几次包含jQuery的奇怪行为,特别是在使用AJAX时.具体来说,为什么不止一次将同一个JavaScript库包含在一个坏主意中呢?为什么它有时只会引起问题?

sim*_*aun 37

根据库,包括它不止一次可能会产生不良影响.

想象一下,如果你有一个脚本将click事件绑定到一个按钮,并且你包含该脚本两次,那么当单击该按钮时,这些动作将运行两次.

您可以编写一个简单的函数,您可以调用该函数来加载脚本并让它跟踪已加载的文件.或者,我确信您可能使用预先存在的JS加载程序(如LabJS)并对其进行修改.

  • 这完全是关于*重新进入*.刚才是"模块加载"而不是功能执行.设计师是否做了一些(愚蠢的)会使第二次包含*破坏*逻辑?通常情况并非如此,但可以想象它确实存在的情况 - 特别是在每次运行依赖于某些外部状态且逻辑被错误应用的情况下. (3认同)

Ste*_*hen 11

您应该采用我学习的方法来检查HTML5 Boilerplate的来源:

<script>
    !window.YAHOO && document.write(
        unescape('%3Cscript src="/js/yahoo/yahoo-min.js"%3E%3C/script%3E')
    );
</script>
Run Code Online (Sandbox Code Playgroud)

我不使用YUI,所以替换!window.YAHOO为全球YUI使用的任何东西.

如果库尚未存在于全局范围内,则此方法仅加载库.

  • 有很多方法可以做到这一点,而无需求助于具有各种问题的“document.write”。HTML5 Boilerplate 不再使用这段代码。 (2认同)

Júl*_*tos 6

浏览器将缓存文件,只下载一次.然而,它将被执行多次.因此,性能影响可以忽略不计,但正确性影响可能不大.

  • 不过,它会不止一次地对它进行评估. (13认同)
  • úlio评估可能并不昂贵(就时间而言,或者在这种情况下,心跳)但可能导致您的代码无法按预期工作.作为一个例子......加载jQuery,然后是jQuery UI,然后是一些自定义的jQuery UI小部件.然后再次加载jQuery UI并呐喊!您的自定义小部件不再存在! (9认同)
  • úlio,这个评论没有任何意义. (3认同)

Fli*_*imm 5

每次都会执行。根据文件的不同,这可能是不可取的。例如,如果文件包含alert("hello"),则每次引用该文件时都会显示警告框,您可能希望它只显示一次。

编写安全库:

如果您只想要一次性执行,以下是您解决此问题的方法。假设您正在编写一个库foobar.js,它导出一个全局变量foobar:

function foobar() {
 // ...
}
Run Code Online (Sandbox Code Playgroud)

您可以使用如下代码确保文件的任何重复执行都变为无操作:

window.foobar = window.foobar || function foobar() {
  // ...
};
Run Code Online (Sandbox Code Playgroud)

更现代的方法是改用JavaScript 模块。JavaScript 模块最多只执行一次:

<script type="module" src="example.js"></script>
<script type="module" src="example.js"></script>
<!-- example.js will only be executed once -->
Run Code Online (Sandbox Code Playgroud)

使用不安全的库:

如果您无法修改库的源代码,并且您确定它不安全,那么这里有一种解决方法,即只加载一次库。创建一个全局并每次使用它来检查脚本是否已经加载。您必须自己将全局设置为 true。

<script>(function() {
  if (! window.foobar) {
    var script = document.createElement('script');
    script.async = true; // remove this if you don't want the script to be async
    script.src = 'foobar.js';
    document.getElementsByTagName('head')[0].appendChild(script);
    window.foobar = true;
 }
}();</script>
Run Code Online (Sandbox Code Playgroud)