两次包含同一个 JavaScript 库有什么危险?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4891278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:15:14  来源:igfitidea点击:

What is the danger in including the same JavaScript library twice?

javascriptjavascript-framework

提问by Eric the Red

One of the webapps I'm working in is made up of many partial HTML files. If the partial requires a JavaScript library such as YUI, the YUI library is included in the partial.

我正在使用的 web 应用程序之一由许多部分 HTML 文件组成。如果部分需要 JavaScript 库(例如 YUI),则 YUI 库包含在部分中。

When the partials are combined at runtime, the resulting HTML often includes the YUI library several times.

在运行时组合部分时,生成的 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>

I've seen strange behavior from including jQuery several times, especially when using AJAX. Why, specifically, is including the same JavaScript library more than once a bad idea? Why does it only sometimes cause problems?

我曾多次看到包含 jQuery 的奇怪行为,尤其是在使用 AJAX 时。具体来说,为什么多次包含同一个 JavaScript 库是个坏主意?为什么它只是有时会导致问题?

采纳答案by simshaun

Depending on the library, including it more than once could have undesired effects.

根据库的不同,多次包含它可能会产生不良影响。

Think of it like this, if you have a script that binds a click event to a button, and you include that script twice, those actions will be ran twice when the button is clicked.

可以这样想,如果您有一个将单击事件绑定到按钮的脚本,并且您包含该脚本两次,那么单击按钮时这些操作将运行两次。

You could write a simple function that you call to load a script and have it keep track of files that have already been loaded. Or, I'm sure you could probably use a pre-existing JS loader such as LabJS and modify it.

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

回答by Stephen

You should take an approach I learned examining the source of HTML5 Boilerplate:

您应该采用我在检查HTML5 Boilerplate源代码时学到的方法:

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

I don't use YUI, so replace !window.YAHOOwith whatever global YUI uses.

我不使用 YUI,所以替换!window.YAHOO为全局 YUI 使用的任何内容。

This approach will only load the library if it does not yet exist in the global scope.

如果库不存在于全局范围内,这种方法只会加载库。

回答by Júlio Santos

The browser will cache the file, downloading it only once. It will be executed more than once however. So the performance impact is negligible, but the correctness impact might not be.

浏览器将缓存文件,只下载一次。然而,它将被执行不止一次。所以性能影响可以忽略不计,但正确性影响可能不是。

回答by Flimm

It gets executed each time. Dependending on the file, this may be undesirable. For instance, if the file contains alert("hello"), it will display the alert box for every time the file is referenced, and you may have intended for it to be only displayed once.

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

Writing safe libraries:

编写安全的库:

Here's how you work around it if you only want a one-time execution. Let's say you're writing a library foobar.js, which exports one global, foobar:

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

function foobar() {
 // ...
}

You could make sure that any repeat executions of the file become no-ops, using code like this:

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

window.foobar = window.foobar || function foobar() {
  // ...
};

A more modern approach would be to use JavaScript modulesinstead. JavaScript modules are only ever executed at most once:

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

<script type="module" src="example.js"></script>
<script type="module" src="example.js"></script>
<!-- example.js will only be executed once -->

Using unsafe libraries:

使用不安全的库:

If you can't modify the source code of the library, and you've determined it's unsafe, here's one way to work around it to load the library only once. Create a global and use it each time to check if the script has already been loaded. You'll have to set the global to true yourself.

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