如何将一个 JavaScript 文件包含到另一个 JavaScript 文件中?
如何将一个 JavaScript 文件包含在另一个 JavaScript 文件中,类似于 CSS 中的
@import
?
JavaScript的旧版本没有进口,包括或需要,已经开发了许多不同的方法。 “ http://exploringjs.com/es6/ch_modules.html” rel =“ noreferrer”> es6模块 在node.js中导入模块的标准,这也由 大多数现代浏览器 。
,用于与较旧浏览器的兼容,构建诸如 webpack 和 crolup babel 可以使用。
es6模块
ecmascript(es6)模块已经
node.js
自V8.5以来,
- 带有
>或给文件扩展名
- 实验性 - 模块
flag,以及至少没有标志的node.js v13.8.0。要启用“ ESM”(vs. Node.js的先前CONCORJS风格模块系统[“ CJS”])您要么在
poffage.json
“ type”:“ module”
.mjs
。 (同样,使用node.js编写的模块可以命名为
.cjs
,如果您的默认值为ESM。)
使用
package.json.json
:
298314851
然后
module.js
:
3279777549
然后/code>:
690648567
使用
.mjs
,您将拥有
module.mjs
:
然后
main.mjs
:
774582211
浏览器中的ecmascript模块
浏览器支持直接加载ecmascript模块(不需要WebPack之类的工具)
10.1,Chrome 61,Firefox 60和Edge 16.在
caniuse
上检查当前支撑。无需使用node.js'
.mjs
扩展名;浏览器完全忽略模块/脚本上的文件扩展。
241424587
171551509
https://jakearchearchibald.com/2017/es-modules-in-browsers/
浏览器中的动态导入/h3>
动态导入,让脚本按需要加载其他脚本:
125477055
阅读更多信息,请访问 https://developers.google.com/web/updates/2017/11/dynamic-import
node.js require
node.js中仍然广泛使用的旧cjs模块样式是
module.exports
/
要求
System。 JavaScript还有其他方法在不需要预处理的浏览器中包含外部JavaScript内容。
AJAX 加载
您可以使用 AJAX 调用加载其他脚本,然后使用
eval
运行它。这是最直接的方法,但由于 JavaScript 沙盒安全模型,它仅限于您的域。使用
eval
也容易导致错误、黑客攻击和安全问题。
获取加载
与动态导入类似,您可以使用
fetch
调用加载一个或多个脚本,并使用承诺控制脚本依赖项的执行顺序,使用
Fetch Inject
库:
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
jQuery 加载
jQuery 库在一行中提供加载功能:
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
动态脚本加载
您可以在 HTML 中添加带有脚本 URL 的脚本标记。为了避免 jQuery 的开销,这是一个理想的解决方案。
脚本甚至可以驻留在不同的服务器上。此外,浏览器会评估代码。
<script>
标签可以注入到网页
<head>
中,也可以插入到结束
</body>
标签之前。
下面是其工作原理的示例:
function dynamicallyLoadScript(url) {
var script = document.createElement("script"); // create a script DOM node
script.src = url; // set its src to the provided URL
document.head.appendChild(script); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}
此函数将在页面 head 部分的末尾添加一个新的
<script>
标签,其中
src
属性设置为作为第一个参数提供给函数的 URL。
JavaScript Madness: Dynamic Sc​​ript Loading 中讨论和说明了这两种解决方案。
检测脚本何时执行
现在,有一个大问题您必须知道。这样做意味着 您远程加载代码 。现代网络浏览器将加载文件并继续执行当前脚本,因为它们异步加载所有内容以提高性能。(这适用于 jQuery 方法和手动动态脚本加载方法。)
这意味着如果您直接使用这些技巧, 您将无法在要求加载后在下一行使用新加载的代码 ,因为它仍在加载。
例如:
my_lovely_script.js
包含
MySuperObject
:
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
var s = new MySuperObject();
Error : MySuperObject is undefined
然后您按 F5 重新加载页面。它有效!令人困惑......
那么该怎么办?
好吧,您可以使用作者在我给您的链接中建议的黑客攻击。总之,对于急需的人来说,他在脚本加载时使用事件来运行回调函数。因此,您可以将所有使用远程库的代码放在回调函数中。例如:
function loadScript(url, callback)
{
// Adding the script tag to the head as suggested before
var head = document.head;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
然后,在 lambda 函数 中编写要在脚本加载后使用的代码:
var myPrettyCode = function() {
// Here, do whatever you want
};
然后运行所有这些:
loadScript("my_lovely_script.js", myPrettyCode);
请注意,脚本可能在 DOM 加载之后或之前执行,具体取决于浏览器以及是否包含行
script.async = false;
。有一篇
关于 JavaScript 加载的精彩文章
对此进行了讨论。
源代码合并/预处理
正如本答案开头所述,许多开发人员在他们的项目中使用 Parcel、Webpack 或 Babel 等构建/转译工具,允许他们使用即将推出的 JavaScript 语法、为旧版浏览器提供向后兼容性、合并文件、最小化、执行代码拆分等。
如果有人正在寻找更高级的东西,请尝试 RequireJS 。您将获得额外的好处,例如依赖项管理、更好的并发性以及避免重复(即多次检索脚本)。
您可以在“模块”中编写 JavaScript 文件,然后在其他脚本中将其作为依赖项引用。或者您可以使用 RequireJS 作为一个简单的“获取此脚本”解决方案。
示例:
将依赖项定义为模块:
some-dependency.js
define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {
//Your actual script goes here.
//The dependent scripts will be fetched if necessary.
return libraryObject; //For example, jQuery object
});
implementation.js 是依赖于 some-dependency.js
require(['some-dependency'], function(dependency) {
//Your script goes here
//some-dependency.js is fetched.
//Then your script is executed
});
摘自 GitHub README:
RequireJS loads plain JavaScript files as well as more defined modules. It is optimized for in-browser use, including in a Web Worker, but it can be used in other JavaScript environments, like Rhino and Node. It implements the Asynchronous Module API.
RequireJS uses plain script tags to load modules/files, so it should allow for easy debugging. It can be used simply to load existing JavaScript files, so you can add it to your existing project without having to re-write your JavaScript files.
...
实际上 有 一种方法可以 非 异步加载 JavaScript 文件,因此您可以在加载新加载的文件后立即使用其中包含的函数,我认为它适用于所有浏览器。
您需要在页面的
<head>
元素上使用
jQuery.append()
,即:
$("head").append($("<script></script>").attr("src", url));
/* Note that following line of code is incorrect because it doesn't escape the
* HTML attribute src correctly and will fail if `url` contains special characters:
* $("head").append('<script src="' + url + '"></script>');
*/
但是,这种方法也存在一个问题:如果在导入的 JavaScript 文件中发生错误, Firebug (以及 Firefox 错误控制台和 Chrome 开发者工具 )将错误地报告其位置,如果您使用Firebug 可以大量追踪 JavaScript 错误(我就是这么做的)。由于某种原因,Firebug 根本不知道新加载的文件,因此如果该文件中出现错误,它会报告该错误发生在您的主 HTML 文件中,您将很难找出错误的真正原因。
但如果这对您来说不是问题,那么这种方法应该有效。
我实际上编写了一个名为 $.import_js() 的 jQuery 插件,它使用这种方法:
(function($)
{
/*
* $.import_js() helper (for JavaScript importing within JavaScript code).
*/
var import_js_imported = [];
$.extend(true,
{
import_js : function(script)
{
var found = false;
for (var i = 0; i < import_js_imported.length; i++)
if (import_js_imported[i] == script) {
found = true;
break;
}
if (found == false) {
$("head").append($('<script></script').attr('src', script));
import_js_imported.push(script);
}
}
});
})(jQuery);
因此,导入 JavaScript 所需要做的所有事情是:
$.import_js('/path_to_project/scripts/somefunctions.js');
我也在 Example 中对此进行了一个简单的测试。
它包括一个
main.js
文件在主 HTML 中,然后
main.js
中的脚本使用
$.import_js()
导入一个名为
included.js
的附加文件,该文件定义了以下函数:
function hello()
{
alert("Hello world!");
}
在包含
included.js
之后,将调用
hello()
函数,然后您会收到警报。
(这个答案是对 e-satis 评论的回应)。