开发者问题收集

如何将一个 JavaScript 文件包含到另一个 JavaScript 文件中?

2009-06-04
4416408

如何将一个 JavaScript 文件包含在另一个 JavaScript 文件中,类似于 CSS 中的 @import

3个回答

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

<代码> 892450828

然后 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 语法、为旧版浏览器提供向后兼容性、合并文件、最小化、执行代码拆分等。

Bite code
2009-06-04

如果有人正在寻找更高级的东西,请尝试 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.

...

John Strickler
2012-06-07

实际上 一种方法可以 异步加载 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 评论的回应)。

Kipras
2011-04-28