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

[英]How do I include a JavaScript file in another JavaScript file?


Is there something in JavaScript similar to @import in CSS that allows you to include a JavaScript file inside another JavaScript file?

JavaScript中是否存在与@import相似的内容,允许您将JavaScript文件包含在另一个JavaScript文件中?

55 个解决方案

#1


The old versions of JavaScript had no import, include, or require, so many different approaches to this problem have been developed.

旧版本的JavaScript没有导入,包含或要求,因此开发了许多不同的方法来解决这个问题。

But since 2015 (ES6), JavaScript has had the ES6 modules standard to import modules in Node.js, which is also supported by most modern browsers.

但自2015年(ES6)以来,JavaScript已经有了ES6模块标准来导入Node.js中的模块,大多数现代浏览器也支持这些模块。

For compatibility with older browsers, build and/or transpilation tools can be used.

为了与旧版浏览器兼容,可以使用构建和/或转换工具。

ES6 Modules

ECMAScript (ES6) modules have been supported in Node.js since v8.5, with the --experimental-modules flag. All files involved must have the .mjs extension.

自v8.5起,Node.js支持ECMAScript(ES6)模块,带有--experimental-modules标志。涉及的所有文件必须具有.mjs扩展名。

// module.mjsexport function hello() {  return "Hello";}
// main.mjsimport { hello } from 'module'; // or './module'let val = hello();  // val is "Hello";

ECMAScript modules in browsers

Browsers have had support for loading ECMAScript modules directly (no tools like Webpack required) since Safari 10.1, Chrome 61, Firefox 60, and Edge 16. Check the current support at caniuse.

自Safari 10.1,Chrome 61,Firefox 60和Edge 16以来,浏览器已经支持直接加载ECMAScript模块(不需要像Webpack这样的工具)。检查caniuse的当前支持。

<script type="module">  import { hello } from './hello.mjs';  hello('world');</script>
// hello.mjsexport function hello(text) {  const div = document.createElement('div');  div.textContent = `Hello ${text}`;  document.body.appendChild(div);}

Read more at https://jakearchibald.com/2017/es-modules-in-browsers/

欲了解更多信息,请访问https://jakearchibald.com/2017/es-modules-in-browsers/

Dynamic imports in browsers

Dynamic imports let the script load other scripts as needed:

动态导入允许脚本根据需要加载其他脚本:

<script type="module">  import('hello.mjs').then(module => {      module.hello('world');    });</script>

Read more at https://developers.google.com/web/updates/2017/11/dynamic-import

有关详情,请访问https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js require

The old style of importing modules, still widely used in Node.js, is the module.exports/require system.

仍然在Node.js中广泛使用的旧模式导入模块是module.exports / require系统。

// mymodule.jsmodule.exports = {   hello: function() {      return "Hello";   }}
// server.jsconst myModule = require('./mymodule');let val = myModule.hello(); // val is "Hello"   

There are other ways for JavaScript to include external JavaScript contents in browsers that do not require preprocessing.

JavaScript还有其他方法可以在不需要预处理的浏览器中包含外部JavaScript内容。

AJAX Loading

You could load an additional script with an AJAX call and then use eval to run it. This is the most straightforward way, but it is limited to your domain because of the JavaScript sandbox security model. Using eval also opens the door to bugs, hacks and security issues.

您可以使用AJAX调用加载其他脚本,然后使用eval运行它。这是最简单的方法,但由于JavaScript沙箱安全模型,它仅限于您的域。使用eval还可以打开错误,黑客和安全问题的大门。

Fetch Loading

Like Dynamic Imports you can load one or many scripts with a fetch call using promises to control order of execution for script dependencies using the Fetch Inject library:

与Dynamic Imports一样,您可以使用promises加载一个或多个带有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 Loading

The jQuery library provides loading functionality in one line:

jQuery库在一行中提供加载功能:

$.getScript("my_lovely_script.js", function() {   alert("Script loaded but not necessarily executed.");});

Dynamic Script Loading

You could add a script tag with the script URL into the HTML. To avoid the overhead of jQuery, this is an ideal solution.

您可以将带有脚本URL的脚本标记添加到HTML中。为了避免jQuery的开销,这是一个理想的解决方案。

The script can even reside on a different server. Furthermore, the browser evaluates the code. The <script> tag can be injected into either the web page <head>, or inserted just before the closing </body> tag.

该脚本甚至可以驻留在不同的服务器上。此外,浏览器评估代码。

Here is an example of how this could work:

以下是一个如何工作的示例:

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)}

This function will add a new <script> tag to the end of the head section of the page, where the src attribute is set to the URL which is given to the function as the first parameter.

此函数将新的

Both of these solutions are discussed and illustrated in JavaScript Madness: Dynamic Script Loading.

这两个解决方案都在JavaScript疯狂:动态脚本加载中进行了讨论和说明。

Detecting when the script has been executed

Now, there is a big issue you must know about. Doing that implies that you remotely load the code. Modern web browsers will load the file and keep executing your current script because they load everything asynchronously to improve performance. (This applies to both the jQuery method and the manual dynamic script loading method.)

现在,您必须了解一个大问题。这样做意味着您远程加载代码。现代Web浏览器将加载文件并继续执行当前脚本,因为它们异步加载所有内容以提高性能。 (这适用于jQuery方法和手动动态脚本加载方法。)

It means that if you use these tricks directly, you won't be able to use your newly loaded code the next line after you asked it to be loaded, because it will be still loading.

这意味着如果你直接使用这些技巧,在你要求加载后,你将无法在下一行使用新加载的代码,因为它仍然会加载。

For example: my_lovely_script.js contains MySuperObject:

例如: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

Then you reload the page hitting F5. And it works! Confusing...

然后你重新加载页面击中F5。它的工作原理!混乱...

So what to do about it ?

那该怎么办呢?

Well, you can use the hack the author suggests in the link I gave you. In summary, for people in a hurry, he uses an event to run a callback function when the script is loaded. So you can put all the code using the remote library in the callback function. For example:

好吧,你可以在我给你的链接中使用作者建议的黑客。总之,对于匆忙的人,他在加载脚本时使用事件来运行回调函数。因此,您可以使用远程库将所有代码放在回调函数中。例如:

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);}

Then you write the code you want to use AFTER the script is loaded in a lambda function:

然后在lambda函数中加载脚本后编写要使用的代码:

var myPrettyCode = function() {   // Here, do whatever you want};

Then you run all that:

然后你运行所有:

loadScript("my_lovely_script.js", myPrettyCode);

Note that the script may execute after the DOM has loaded, or before, depending on the browser and whether you included the line script.async = false;. There's a great article on Javascript loading in general which discusses this.

请注意,脚本可以在DOM加载之后或之前执行,具体取决于浏览器以及是否包含行script.async = false;。有一篇关于Javascript加载的文章,讨论了这个问题。

Source Code Merge/Preprocessing

As mentioned at the top of this answer, many developers use build/transpilation tool(s) like Parcel, Webpack, or Babel in their projects, allowing them to use upcoming JavaScript syntax, provide backward compatibility for older browsers, combine files, minify, perform code splitting etc.

正如在本答案的顶部所提到的,许多开发人员在他们的项目中使用像Parcel,Webpack或Babel这样的构建/转换工具,允许他们使用即将推出的JavaScript语法,为旧浏览器提供向后兼容性,组合文件,缩小,执行代码拆分等

#2


If anyone is looking for something more advanced, try out RequireJS. You'll get added benefits such as dependency management, better concurrency, and avoid duplication (that is, retrieving a script more than once).

如果有人正在寻找更高级的东西,请尝试RequireJS。您将获得额外的好处,例如依赖关系管理,更好的并发性,并避免重复(即,多次检索脚本)。

You can write your JavaScript files in "modules" and then reference them as dependencies in other scripts. Or you can use RequireJS as a simple "go get this script" solution.

您可以在“模块”中编写JavaScript文件,然后在其他脚本中将它们作为依赖项引用。或者您可以将RequireJS用作简单的“go get this script”解决方案。

Example:

Define dependencies as modules:

将依赖项定义为模块:

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 is your "main" JavaScript file that depends on some-dependency.js

implementation.js是依赖some-dependency.js的“主”JavaScript文件

require(['some-dependency'], function(dependency) {    //Your script goes here    //some-dependency.js is fetched.       //Then your script is executed});

Excerpt from the GitHub README:

摘自GitHub自述文件:

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加载纯JavaScript文件以及更多已定义的模块。它针对浏览器内使用进行了优化,包括在Web Worker中,但它可以在其他JavaScript环境中使用,如Rhino和Node。它实现了异步模块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.

RequireJS使用普通脚本标签来加载模块/文件,因此它应该允许轻松调试。它可以简单地用于加载现有的JavaScript文件,因此您可以将其添加到现有项目中,而无需重新编写JavaScript文件。

...

#3


There actually is a way to load a JavaScript file not asynchronously, so you could use the functions included in your newly loaded file right after loading it, and I think it works in all browsers.

实际上有一种方法可以非异步地加载JavaScript文件,因此您可以在加载后立即使用新加载的文件中包含的函数,我认为它适用于所有浏览器。

You need to use jQuery.append() on the <head> element of your page, that is:

您需要在页面的元素上使用jQuery.append(),即:

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

However, this method also has a problem: if an error happens in the imported JavaScript file, Firebug (and also Firefox Error Console and Chrome Developer Tools as well) will report its place incorrectly, which is a big problem if you use Firebug to track JavaScript errors down a lot (I do). Firebug simply doesn't know about the newly loaded file for some reason, so if an error occurs in that file, it reports that it occurred in your main HTML file, and you will have trouble finding out the real reason for the error.

但是,此方法也存在一个问题:如果导入的JavaScript文件中发生错误,Firebug(以及Firefox错误控制台和Chrome开发人员工具)也会错误地报告其位置,如果您使用Firebug跟踪这是一个大问题JavaScript错误很多(我这样做)。由于某种原因,Firebug根本不知道新加载的文件,因此如果该文件中出现错误,它会报告它发生在您的主HTML文件中,并且您将无法找到错误的真正原因。

But if that is not a problem for you, then this method should work.

但如果这对你来说不是问题,那么这种方法应该可行。

I have actually written a jQuery plugin called $.import_js() which uses this method:

我实际上编写了一个名为$ .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 type="text/javascript" src="' + script + '"></script>');                import_js_imported.push(script);            }        }    });})(jQuery);

So all you would need to do to import JavaScript is:

所以你需要做的就是导入JavaScript:

$.import_js('/path_to_project/scripts/somefunctions.js');

I also made a simple test for this at Example.

我也在Example中做了一个简单的测试。

It includes a main.js file in the main HTML and then the script in main.js uses $.import_js() to import an additional file called included.js, which defines this function:

它包含主HTML中的main.js文件,然后main.js中的脚本使用$ .import_js()来导入名为included.js的附加文件,该文件定义了此函数:

function hello(){    alert("Hello world!");}

And right after including included.js, the hello() function is called, and you get the alert.

在包含included.js之后,调用hello()函数,然后获得警报。

(This answer is in response to e-satis' comment).

(这个答案是对e-satisf'评论的回应)。

#4


Another way, that in my opinion is much cleaner, is to make a synchronous Ajax request instead of using a <script> tag. Which is also how Node.js handles includes.

另一种方式,在我看来更清晰,是制作同步Ajax请求而不是使用

Here's an example using jQuery:

这是使用jQuery的一个例子:

function require(script) {    $.ajax({        url: script,        dataType: "script",        async: false,           // <-- This is the key        success: function () {            // all good...        },        error: function () {            throw new Error("Could not load script " + script);        }    });}

You can then use it in your code as you'd usually use an include:

然后,您可以在代码中使用它,因为您通常使用包含:

require("/scripts/subscript.js");

And be able to call a function from the required script in the next line:

并且能够在下一行中从所需脚本调用函数:

subscript.doSomethingCool(); 

#5


There is a good news for you. Very soon you will be able to load JavaScript code easily. It will become a standard way of importing modules of JavaScript code and will be part of core JavaScript itself.

对你来说有一个好消息。很快您就可以轻松加载JavaScript代码了。它将成为导入JavaScript代码模块的标准方式,并将成为核心JavaScript本身的一部分。

You simply have to write import cond from 'cond.js'; to load a macro named cond from a file cond.js.

你只需要从'cond.js'写下import cond;从文件cond.js加载名为cond的宏。

So you don't have to rely upon any JavaScript framework nor do you have to explicitly make Ajax calls.

因此,您不必依赖任何JavaScript框架,也不必显式地进行Ajax调用。

Refer to:

#6


It is possible to dynamically generate a JavaScript tag and append it to HTML document from inside other JavaScript code. This will load targeted JavaScript file.

可以动态生成JavaScript标记,并将其从其他JavaScript代码中添加到HTML文档中。这将加载有针对性的JavaScript文件。

function includeJs(jsFilePath) {    var js = document.createElement("script");    js.type = "text/javascript";    js.src = jsFilePath;    document.body.appendChild(js);}includeJs("/path/to/some/file.js");

#7


Statement import is in ECMAScript 6.

语句导入在ECMAScript 6中。

Syntax

import name from "module-name";import { member } from "module-name";import { member as alias } from "module-name";import { member1 , member2 } from "module-name";import { member1 , member2 as alias2 , [...] } from "module-name";import name , { member [ , [...] ] } from "module-name";import "module-name" as name;

#8


Maybe you can use this function that I found on this page How do I include a JavaScript file in a JavaScript file?:

也许您可以使用我在此页面上找到的此功能如何在JavaScript文件中包含JavaScript文件?:

function include(filename){    var head = document.getElementsByTagName('head')[0];    var script = document.createElement('script');    script.src = filename;    script.type = 'text/javascript';    head.appendChild(script)}

#9


Here is a synchronous version without jQuery:

这是没有jQuery的同步版本:

function myRequire( url ) {    var ajax = new XMLHttpRequest();    ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous    ajax.onreadystatechange = function () {        var script = ajax.response || ajax.responseText;        if (ajax.readyState === 4) {            switch( ajax.status) {                case 200:                    eval.apply( window, [script] );                    console.log("script loaded: ", url);                    break;                default:                    console.log("ERROR: script not loaded: ", url);            }        }    };    ajax.send(null);}

Note that to get this working cross-domain, the server will need to set allow-origin header in its response.

请注意,要使此跨域工作,服务器需要在其响应中设置allow-origin标头。

#10


I just wrote this JavaScript code (using Prototype for DOM manipulation):

我刚写了这个JavaScript代码(使用Prototype进行DOM操作):

var require = (function() {    var _required = {};    return (function(url, callback) {        if (typeof url == 'object') {            // We've (hopefully) got an array: time to chain!            if (url.length > 1) {                // Load the nth file as soon as everything up to the                // n-1th one is done.                require(url.slice(0, url.length - 1), function() {                    require(url[url.length - 1], callback);                });            } else if (url.length == 1) {                require(url[0], callback);            }            return;        }        if (typeof _required[url] == 'undefined') {            // Haven't loaded this URL yet; gogogo!            _required[url] = [];            var script = new Element('script', {                src: url,                type: 'text/javascript'            });            script.observe('load', function() {                console.log("script " + url + " loaded.");                _required[url].each(function(cb) {                    cb.call(); // TODO: does this execute in the right context?                });                _required[url] = true;            });            $$('head')[0].insert(script);        } else if (typeof _required[url] == 'boolean') {            // We already loaded the thing, so go ahead.            if (callback) {                callback.call();            }            return;        }        if (callback) {            _required[url].push(callback);        }    });})();

Usage:

<script src="prototype.js"></script><script src="require.js"></script><script>    require(['foo.js','bar.js'], function () {        /* Use foo.js and bar.js here */    });</script>

Gist: http://gist.github.com/284442.

#11


Here's the generalized version of how Facebook does it for their ubiquitous Like button:

以下是Facebook为普遍使用的Like按钮做广告的一般化版本:

<script>  var firstScript = document.getElementsByTagName('script')[0],      js = document.createElement('script');  js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';  js.onload = function () {    // do stuff with your dynamically loaded script    snowStorm.snowColor = '#99ccff';  };  firstScript.parentNode.insertBefore(js, firstScript);</script>

If it works for Facebook, it will work for you.

如果适用于Facebook,它将适合您。

The reason why we look for the first script element instead of head or body is because some browsers don't create one if missing, but we're guaranteed to have a script element - this one. Read more at http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/.

我们寻找第一个脚本元素而不是头部或主体的原因是因为某些浏览器在缺少时不创建一个,但我们保证有一个脚本元素 - 这个。欲了解更多信息,请访问http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/。

#12


If you want in pure JavaScript, you can use document.write.

如果你想要纯JavaScript,你可以使用document.write。

document.write('<script src="myscript.js" type="text/javascript"></script>');

If you use the jQuery library, you can use the $.getScript method.

如果使用jQuery库,则可以使用$ .getScript方法。

$.getScript("another_script.js");

#13


You can also assemble your scripts using PHP:

您还可以使用PHP组装脚本:

File main.js.php:

<?php    header('Content-type:text/javascript; charset=utf-8');    include_once("foo.js.php");    include_once("bar.js.php");?>// Main JavaScript code goes here

#14


Most of solutions shown here imply dynamical loading. I was searching instead for a compiler which assemble all the depended files into a single output file. The same as Less/Sass preprocessors deal with the CSS @import at-rule. Since I didn't find anything decent of this sort, I wrote a simple tool solving the issue.

此处显示的大多数解决方案都意味着动态加载。我正在搜索一个编译器,它将所有依赖的文件组合成一个输出文件。与Less / Sass预处理器相同,处理CSS @import at-rule。由于我没有找到这种类似的东西,我写了一个简单的工具来解决这个问题。

So here is the compiler, https://github.com/dsheiko/jsic, which replaces $import("file-path") with the requested file content securely. Here is the corresponding Grunt plugin: https://github.com/dsheiko/grunt-jsic.

所以这里是编译器,https://github.com/dsheiko/jsic,它安全地用所请求的文件内容替换$ import(“文件路径”)。这是相应的Grunt插件:https://github.com/dsheiko/grunt-jsic。

On the jQuery master branch, they simply concatenate atomic source files into a single one starting with intro.js and ending with outtro.js. That doesn't suits me as it provides no flexibility on the source code design. Check out how it works with jsic:

在jQuery master分支上,他们只是简单地将原子源文件连接成一个以intro.js开头并以outtro.js结尾的文件。这不适合我,因为它没有提供源代码设计的灵活性。看看它如何与jsic一起使用:

src/main.js

var foo = $import("./Form/Input/Tel");

src/Form/Input/Tel.js

function() {    return {          prop: "",          method: function(){}    }}

Now we can run the compiler:

现在我们可以运行编译器了:

node jsic.js src/main.js build/mail.js

And get the combined file

并获得组合文件

build/main.js

var foo = function() {    return {          prop: "",          method: function(){}    }};

#15


If your intention to load the JavaScript file is using the functions from the imported/included file, you can also define a global object and set the functions as object items. For instance:

如果您要加载JavaScript文件的意图是使用导入/包含文件中的函数,您还可以定义全局对象并将函数设置为对象项。例如:

global.js

A = {};

file1.js

A.func1 = function() {  console.log("func1");}

file2.js

A.func2 = function() {  console.log("func2");}

main.js

A.func1();A.func2();

You just need to be careful when you are including scripts in an HTML file. The order should be as in below:

在HTML文件中包含脚本时,您需要小心。订单应如下所示:

<head>  <script type="text/javascript" src="global.js"></script>  <script type="text/javascript" src="file1.js"></script>  <script type="text/javascript" src="file2.js"></script>  <script type="text/javascript" src="main.js"></script></head>

#16


This should do:

这应该做:

xhr = new XMLHttpRequest();xhr.open("GET", "/soap/ajax/11.0/connection.js", false);xhr.send();eval(xhr.responseText);

#17


Or rather than including at run time, use a script to concatenate prior to upload.

或者不是在运行时包括在上载之前使用脚本连接。

I use Sprockets (I don't know if there are others). You build your JavaScript code in separate files and include comments that are processed by the Sprockets engine as includes. For development you can include files sequentially, then for production to merge them...

我使用链轮(我不知道是否还有其他链轮)。您可以在单独的文件中构建JavaScript代码,并包含由Sprockets引擎作为包括处理的注释。对于开发,您可以按顺序包含文件,然后生产以合并它们...

See also:

#18


I had a simple issue, but I was baffled by responses to this question.

我有一个简单的问题,但我对这个问题的回答感到困惑。

I had to use a variable (myVar1) defined in one JavaScript file (myvariables.js) in another JavaScript file (main.js).

我不得不在另一个JavaScript文件(main.js)中使用一个JavaScript文件(myvariables.js)中定义的变量(myVar1)。

For this I did as below:

为此,我做了如下:

Loaded the JavaScript code in the HTML file, in the correct order, myvariables.js first, then main.js:

以正确的顺序加载HTML文件中的JavaScript代码,首先是myvariables.js,然后是main.js:

<html>    <body onload="bodyReady();" >        <script src="myvariables.js" > </script>        <script src="main.js" > </script>        <!-- Some other code -->    </body></html>

File: myvariables.js

var myVar1 = "I am variable from myvariables.js";

File: main.js

// ...function bodyReady() {    // ...    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed    // ...}// ...

As you saw, I had use a variable in one JavaScript file in another JavaScript file, but I didn't need to include one in another. I just needed to ensure that the first JavaScript file loaded before the second JavaScript file, and, the first JavaScript file's variables are accessible in the second JavaScript file, automatically.

如您所见,我在另一个JavaScript文件中的一个JavaScript文件中使用了一个变量,但我不需要在另一个JavaScript文件中包含一个变量。我只需要确保在第二个JavaScript文件之前加载第一个JavaScript文件,并且第一个JavaScript文件的变量可以在第二个JavaScript文件中自动访问。

This saved my day. I hope this helps.

这节省了我的一天。我希望这有帮助。

#19


In case you are using Web Workers and want to include additional scripts in the scope of the worker, the other answers provided about adding scripts to the head tag, etc. will not work for you.

如果您正在使用Web Workers并希望在worker的范围内包含其他脚本,则提供有关向head标记添加脚本等的其他答案将不适合您。

Fortunately, Web Workers have their own importScripts function which is a global function in the scope of the Web Worker, native to the browser itself as it is part of the specification.

幸运的是,Web Workers有自己的importScripts函数,它是Web Worker范围内的全局函数,是浏览器本身的原生函数,因为它是规范的一部分。

Alternatively, as the second highest voted answer to your question highlights, RequireJS can also handle including scripts inside a Web Worker (likely calling importScripts itself, but with a few other useful features).

或者,作为对您的问题的第二高投票答案,RequireJS还可以处理包含Web Worker中的脚本(可能调用importScripts本身,但具有一些其他有用的功能)。

#20


The @import syntax for achieving CSS-like JavaScript importing is possible using a tool such as Mixture via their special .mix file type (see here). I imagine the application simply uses one of the aforementioned methods interally, though I don't know.

用于实现类似CSS的JavaScript导入的@import语法可以使用诸如Mixture之类的工具通过其特殊的.mix文件类型(参见此处)。我想应用程序只是在内部使用上述方法之一,但我不知道。

From the Mixture documentation on .mix files:

从.mix文件的Mixture文档中:

Mix files are simply .js or .css files with .mix. in the file name. A mix file simply extends the functionality of a normal style or script file and allows you to import and combine.

混合文件只是带有.mix的.js或.css文件。在文件名中。混合文件只是扩展了普通样式或脚本文件的功能,并允许您导入和组合。

Here's an example .mix file that combines multiple .js files into one:

这是一个将多个.js文件合并为一个的.mix文件示例:

// scripts-global.mix.js// Plugins - Global@import "global-plugins/headroom.js";@import "global-plugins/retina-1.1.0.js";@import "global-plugins/isotope.js";@import "global-plugins/jquery.fitvids.js";

Mixture outputs this as scripts-global.js and also as a minified version (scripts-global.min.js).

Mixture将其输出为scripts-global.js,也作为缩小版本(scripts-global.min.js)输出。

Note: I'm not in any way affiliated with Mixture, other than using it as a front-end development tool. I came across this question upon seeing a .mix JavaScript file in action (in one of the Mixture boilerplates) and being a bit confused by it ("you can do this?" I thought to myself). Then I realized that it was an application-specific file type (somewhat disappointing, agreed). Nevertheless, figured the knowledge might be helpful for others.

注意:除了将它用作前端开发工具之外,我与Mixture无任何关联。我看到一个.mix JavaScript文件在运行中(在其中一个Mixture样板中)并且有点混淆(“你能做到这一点吗?”我想到了自己)时遇到了这个问题。然后我意识到这是一个特定于应用程序的文件类型(有点令人失望,同意)。然而,认为这些知识可能对其他人有所帮助。

UPDATE: Mixture is now free (offline).

更新:混合物现在是免费的(离线)。

UPDATE: Mixture is now discontinued. Old mixture releases are still available

更新:混合物现已停产。旧的混合物发布仍然可用

#21


var js = document.createElement("script");js.type = "text/javascript";js.src = jsFilePath;document.body.appendChild(js);

#22


I wrote a simple module that automates the job of importing/including module scripts in JavaScript. For detailed explanation of the code, refer to the blog post JavaScript require / import / include modules.

我编写了一个简单的模块,可以自动执行在JavaScript中导入/包含模块脚本的工作。有关代码的详细说明,请参阅博客文章JavaScript require / import / include模块。

// ----- USAGE -----require('ivar.util.string');require('ivar.net.*');require('ivar/util/array.js');require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');ready(function(){    //Do something when required scripts are loaded});    //--------------------var _rmod = _rmod || {}; //Require module namespace_rmod.LOADED = false;_rmod.on_ready_fn_stack = [];_rmod.libpath = '';_rmod.imported = {};_rmod.loading = {    scripts: {},    length: 0};_rmod.findScriptPath = function(script_name) {    var script_elems = document.getElementsByTagName('script');    for (var i = 0; i < script_elems.length; i++) {        if (script_elems[i].src.endsWith(script_name)) {            var href = window.location.href;            href = href.substring(0, href.lastIndexOf('/'));            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);            return url.substring(href.length+1, url.length);        }    }    return '';};_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark                                                   //the root directory of your library, any library._rmod.injectScript = function(script_name, uri, callback, prepare) {    if(!prepare)        prepare(script_name, uri);    var script_elem = document.createElement('script');    script_elem.type = 'text/javascript';    script_elem.title = script_name;    script_elem.src = uri;    script_elem.async = true;    script_elem.defer = false;    if(!callback)        script_elem.onload = function() {            callback(script_name, uri);        };    document.getElementsByTagName('head')[0].appendChild(script_elem);};_rmod.requirePrepare = function(script_name, uri) {    _rmod.loading.scripts[script_name] = uri;    _rmod.loading.length++;};_rmod.requireCallback = function(script_name, uri) {    _rmod.loading.length--;    delete _rmod.loading.scripts[script_name];    _rmod.imported[script_name] = uri;    if(_rmod.loading.length == 0)        _rmod.onReady();};_rmod.onReady = function() {    if (!_rmod.LOADED) {        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){            _rmod.on_ready_fn_stack[i]();        });        _rmod.LOADED = true;    }};_.rmod = namespaceToUri = function(script_name, url) {    var np = script_name.split('.');    if (np.getLast() === '*') {        np.pop();        np.push('_all');    }    if(!url)        url = '';    script_name = np.join('.');    return  url + np.join('/')+'.js';};//You can rename based on your liking. I chose require, but it//can be called include or anything else that is easy for you//to remember or write, except "import", because it is reserved//for future use.var require = function(script_name) {    var uri = '';    if (script_name.indexOf('/') > -1) {        uri = script_name;        var lastSlash = uri.lastIndexOf('/');        script_name = uri.substring(lastSlash+1, uri.length);    }     else {        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);    }    if (!_rmod.loading.scripts.hasOwnProperty(script_name)     && !_rmod.imported.hasOwnProperty(script_name)) {        _rmod.injectScript(script_name, uri,            _rmod.requireCallback,                _rmod.requirePrepare);    }};var ready = function(fn) {    _rmod.on_ready_fn_stack.push(fn);};

#23


My usual method is:

我通常的方法是:

var require = function (src, cb) {    cb = cb || function () {};    var newScriptTag = document.createElement('script'),        firstScriptTag = document.getElementsByTagName('script')[0];    newScriptTag.src = src;    newScriptTag.async = true;    newScriptTag.onload = newScriptTag.onreadystatechange = function () {        (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());    };    firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);}

It works great and uses no page-reloads for me. I've tried the AJAX method (one of the other answers) but it doesn't seem to work as nicely for me.

它工作得很好,不会为我使用页面重新加载。我已经尝试过AJAX方法(其他一个答案),但它似乎对我来说效果不佳。

Here's an explanation of how the code works for those that are curious: essentially, it creates a new script tag (after the first one) of the URL. It sets it to asynchronous mode so it doesn't block the rest of the code, but calls a callback when the readyState (the state of the content to be loaded) changes to 'loaded'.

下面解释代码如何为那些好奇的代码工作:实际上,它创建了一个新的脚本标记(在第一个之后)。它将其设置为异步模式,因此它不会阻止其余代码,但在readyState(要加载的内容的状态)更改为“已加载”时调用回调。

#24


In modern language it would be

用现代语言来说就是这样

function loadJs( url ){  return new Promise( resolve => {    const script = document.createElement( "script" );    script.src = url;    script.onload = resolve;    document.head.appendChild( script );  });}

#25


This script will add a JavaScript file to the top of any other <script> tag:

此脚本将JavaScript文件添加到任何其他

(function () {    var li = document.createElement('script');     li.type = 'text/javascript';     li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";     li.async=true;     var s = document.getElementsByTagName('script')[0];     s.parentNode.insertBefore(li, s);})();

#26


There is also Head.js. It is very easy to deal with:

还有Head.js.这很容易处理:

head.load("js/jquery.min.js",          "js/jquery.someplugin.js",          "js/jquery.someplugin.css", function() {  alert("Everything is ok!");});

As you see, it's easier than Require.js and as convenient as jQuery's $.getScript method. It also has some advanced features, like conditional loading, feature detection and much more.

如您所见,它比Require.js更容易,并且像jQuery的$ .getScript方法一样方便。它还具有一些高级功能,如条件加载,功能检测等等。

#27


I came to this question because I was looking for a simple way to maintain a collection of useful JavaScript plugins. After seeing some of the solutions here, I came up with this:

我来到这个问题是因为我正在寻找一种简单的方法来维护一组有用的JavaScript插件。在看到这里的一些解决方案之后,我想出了这个:

  1. Set up a file called "plugins.js" (or extensions.js or what have you). Keep your plugin files together with that one master file.

    设置一个名为“plugins.js”(或extensions.js或者你有什么)的文件。将插件文件与一个主文件保持在一起。

  2. plugins.js will have an array called "pluginNames[]" that we will iterate over each(),then append a tag to the head for each plugin

    plugins.js将有一个名为“pluginNames []”的数组,我们将遍历每个(),然后为每个插件追加一个标记到头部

    //set array to be updated when we add or remove plugin files var pluginNames = ["lettering", "fittext", "butterjam", etc.];//one script tag for each plugin $.each(pluginNames, function(){ $('head').append(''); });

    //当我们添加或删除插件文件时设置要更新的数组var pluginNames = [“lettering”,“fittext”,“butterjam”等]; //每个插件的一个脚本标签$ .each(pluginNames,function( ){$('head')。append('');});

  3. manually call just the one file in your head:
    <script src="js/plugins/plugins.js"></script>

    手动调用你头脑中的一个文件:

I found that even though all of the plugins were getting dropped into the head tag the way they ought to, they weren't always being run by the browser when you click into the page or refresh.

我发现即使所有的插件都按照它们应该的方式放入头标签,但当你点击页面或刷新时,它们并不总是被浏览器运行。

I found it's more reliable to just write the script tags in a PHP include. You only have to write it once and that's just as much work as calling the plugin using JavaScript.

我发现在PHP包中编写脚本标记更可靠。你只需要编写一次,这与使用JavaScript调用插件一样重要。

#28


There are a lot of potential answers for this question. My answer is obviously based on a number of them. This is what I ended up with after reading through all the answers.

这个问题有很多潜在的答案。我的回答显然基于其中的一些。这是我在阅读完所有答案后最终得到的结果。

The problem with $.getScript and really any other solution that requires a callback when loading is complete is that if you have multiple files that use it and depend on each other you no longer have a way to know when all scripts have been loaded (once they are nested in multiple files).

$ .getScript以及加载完成时需要回调的任何其他解决方案的问题在于,如果您有多个文件使用它并相互依赖,则您无法知道何时加载了所有脚本(一次它们嵌套在多个文件中)。

Example:

file3.js

var f3obj = "file3";// Define other stuff

file2.js:

var f2obj = "file2";$.getScript("file3.js", function(){    alert(f3obj);    // Use anything defined in file3.});

file1.js:

$.getScript("file2.js", function(){    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.    alert(f2obj);    // Use anything defined in the loaded script...});

You are right when you say that you could specify Ajax to run synchronously or use XMLHttpRequest, but the current trend appears to be to deprecate synchronous requests, so you may not get full browser support now or in the future.

当你说你可以指定Ajax同步运行或使用XMLHttpRequest时,你是对的,但当前的趋势似乎是弃用同步请求,所以你现在或将来可能无法获得完整的浏览器支持。

You could try to use $.when to check an array of deferred objects, but now you are doing this in every file and file2 will be considered loaded as soon as the $.when is executed not when the callback is executed, so file1 still continues execution before file3 is loaded. This really still has the same problem.

您可以尝试使用$ .when来检查延迟对象的数组,但现在您在每个文件中执行此操作,并且只要执行$ .when而不执行回调时,file2将被视为已加载,因此file1仍然在加载file3之前继续执行。这仍然有同样的问题。

I decided to go backwards instead of forwards. Thank you document.writeln. I know it's taboo, but as long as it is used correctly this works well. You end up with code that can be debugged easily, shows in the DOM correctly and can ensure the order the dependencies are loaded correctly.

我决定倒退而不是前锋。谢谢document.writeln。我知道这是禁忌,但只要使用得当,这种方法效果很好。您最终得到的代码可以轻松调试,正确显示在DOM中,并且可以确保正确加载依赖项的顺序。

You can of course use $ ("body").append(), but then you can no longer debug correctly any more.

你当然可以使用$(“body”)。append(),但是你再也无法正确调试了。

NOTE: You must use this only while the page is loading, otherwise you get a blank screen. In other words, always place this before / outside of document.ready. I have not tested using this after the page is loaded in a click event or anything like that, but I am pretty sure it'll fail.

注意:您必须仅在页面加载时使用此选项,否则您将获得一个空白屏幕。换句话说,始终将此放在document.ready之前/之外。在点击事件或类似事件中加载页面后,我没有使用过此测试,但我很确定它会失败。

I liked the idea of extending jQuery, but obviously you don't need to.

我喜欢扩展jQuery的想法,但显然你不需要。

Before calling document.writeln, it checks to make sure the script has not already been loading by evaluating all the script elements.

在调用document.writeln之前,它会通过评估所有脚本元素来检查以确保脚本尚未加载。

I assume that a script is not fully executed until its document.ready event has been executed. (I know using document.ready is not required, but many people use it, and handling this is a safeguard.)

我假设在执行document.ready事件之前,脚本没有完全执行。 (我知道使用document.ready不是必需的,但是很多人使用它,处理这个是一个安全措施。)

When the additional files are loaded the document.ready callbacks will get executed in the wrong order. To address this when a script is actually loaded, the script that imported it is re-imported itself and execution halted. This causes the originating file to now have its document.ready callback executed after any from any scripts that it imports.

加载其他文件时,document.ready回调将以错误的顺序执行。为了在实际加载脚本时解决此问题,导入它的脚本将自行重新导入并停止执行。这会导致原始文件现在在其导入的任何脚本之后执行其document.ready回调。

Instead of this approach you could attempt to modify the jQuery readyList, but this seemed like a worse solution.

您可以尝试修改jQuery readyList,而不是这种方法,但这似乎是一个更糟糕的解决方案。

Solution:

$.extend(true,{    import_js : function(scriptpath, reAddLast)    {        if (typeof reAddLast === "undefined" || reAddLast === null)        {            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.        }        var found = false;        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.        {            found = $('script').filter(function () {                return ($(this).attr('src') == scriptpath);            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.        }        if (found == false) {            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln            if (reAddLast)            {                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.            }            return true;        }        return false;    }});

Usage:

File3:

var f3obj = "file3";// Define other stuff$(function(){    f3obj = "file3docready";});

File2:

$.import_js('js/file3.js');var f2obj = "file2";$(function(){    f2obj = "file2docready";});

File1:

$.import_js('js/file2.js');// Use objects from file2 or file3alert(f3obj); // "file3"alert(f2obj); // "file2"$(function(){    // Use objects from file2 or file3 some more.    alert(f3obj); //"file3docready"    alert(f2obj); //"file2docready"});

#29


I have created a function that will allow you to use similar verbiage to C#/Java to include a JavaScript file. I've tested it a little bit even from inside of another JavaScript file and it seems to work. It does require jQuery though for a bit of "magic" at the end.

我创建了一个函数,允许您使用与C#/ Java类似的措辞来包含JavaScript文件。我甚至从另一个JavaScript文件内部测试了一下它似乎工作。它确实需要jQuery,但最后需要一些“魔术”。

I put this code in a file at the root of my script directory (I named it global.js, but you can use whatever you want. Unless I'm mistaken this and jQuery should be the only required scripts on a given page. Keep in mind this is largely untested beyond some basic usage, so there may or may not be any issues with the way I've done it; use at your own risk yadda yadda I am not responsible if you screw anything up yadda yadda:

我把这段代码放在脚本目录根目录下的文件中(我把它命名为global.js,但你可以使用你想要的任何东西。除非我弄错了,jQuery应该是给定页面上唯一需要的脚本。保持记住,除了一些基本用法之外,这在很大程度上是未经测试的,因此我可能会或可能不会出现任何问题;使用风险yadda yadda我不负责任,如果你搞砸了yadda yadda:

/*** @fileoverview This file stores global functions that are required by other libraries.*/if (typeof(jQuery) === 'undefined') {    throw 'jQuery is required.';}/** Defines the base script directory that all .js files are assumed to be organized under. */var BASE_DIR = 'js/';/*** Loads the specified file, outputting it to the <head> HTMLElement.** This method mimics the use of using in C# or import in Java, allowing* JavaScript files to "load" other JavaScript files that they depend on* using a familiar syntax.** This method assumes all scripts are under a directory at the root and will* append the .js file extension automatically.** @param {string} file A file path to load using C#/Java "dot" syntax.** Example Usage:* imports('core.utils.extensions');* This will output: <script type="text/javascript" src="/js/core/utils/extensions.js"></script>*/function imports(file) {    var fileName = file.substr(file.lastIndexOf('.') + 1, file.length);    // Convert PascalCase name to underscore_separated_name    var regex = new RegExp(/([A-Z])/g);    if (regex.test(fileName)) {        var separated = fileName.replace(regex, ",$1").replace(',', '');        fileName = separated.replace(/[,]/g, '_');    }    // Remove the original JavaScript file name to replace with underscore version    file = file.substr(0, file.lastIndexOf('.'));    // Convert the dot syntax to directory syntax to actually load the file    if (file.indexOf('.') > 0) {        file = file.replace(/[.]/g, '/');    }    var src = BASE_DIR + file + '/' + fileName.toLowerCase() + '.js';    var script = document.createElement('script');    script.type = 'text/javascript';    script.src = src;    $('head').find('script:last').append(script);}

#30


Although these answers are great, there is a simple "solution" that has been around since script loading existed, and it will cover 99.999% of most people's use cases. Just include the script you need before the script that requires it. For most projects it does not take long to determine which scripts are needed and in what order.

虽然这些答案很棒,但是存在一个简单的“解决方案”,因为脚本加载已存在,它将覆盖大多数人的99.999%的用例。只需在需要它的脚本之前包含所需的脚本。对于大多数项目,确定需要哪些脚本以及按什么顺序排列并不需要很长时间。

<!DOCTYPE HTML><html>    <head>        <script src="script1.js"></script>        <script src="script2.js"></script>    </head>    <body></body></html>

If script2 requires script1, this really is the absolute easiest way to do something like this. I'm very surprised no-one has brought this up, as it's the most obvious and simplest answer that will apply in nearly every single case.

如果script2需要script1,这确实是做这样的事情的绝对最简单的方法。我很惊讶没有人提出这个问题,因为这是几乎每一个案例中最明显和最简单的答案。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/06/04/47d6b748a3119911d1bbf32d27a5bde8.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com