喵-见缝插针
2009-06-04 11:59
采纳率: 0%
浏览 520
已采纳

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

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

转载于:https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

30条回答 默认 最新

  • elliott.david 2009-06-04 12:13
    已采纳

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

    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.

    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.

    // module.mjs
    export function hello() {
      return "Hello";
    }
    
    // main.mjs
    import { 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.

    <script type="module">
      import { hello } from './hello.mjs';
      hello('world');
    </script>
    
    // hello.mjs
    export 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/

    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

    Node.js require

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

    // mymodule.js
    module.exports = {
       hello: function() {
          return "Hello";
       }
    }
    
    // server.js
    const 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.

    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.

    jQuery Loading

    The jQuery library provides loading functionality in one line:

    $.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.

    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 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.

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

    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:

    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...

    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.getElementsByTagName('head')[0];
        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:

    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.

    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 backwards compatibility for older browsers, combine files, minify, perform code splitting etc.

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • 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.

    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");
    
    评论
    解决 无用
    打赏 举报
  • lrony* 2009-06-04 12:04

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

    function include(filename)
    {
        var head = document.getElementsByTagName('head')[0];
    
        var script = document.createElement('script');
        script.src = filename;
        script.type = 'text/javascript';
    
        head.appendChild(script)
    }
    
    评论
    解决 无用
    打赏 举报
  • 旧行李 2010-01-23 05:20

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

    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.

    评论
    解决 无用
    打赏 举报
  • Lotus@ 2010-12-27 21:03

    You can also assemble your scripts using 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
    
    评论
    解决 无用
    打赏 举报
  • 妄徒之命 2011-04-28 15:25

    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.

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

    $("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.

    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:

    (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:

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

    I also made a simple test for this at 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:

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

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

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

    评论
    解决 无用
    打赏 举报
  • YaoRaoLov 2011-09-08 18:22

    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.

    Here's an example using 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(); 
    
    评论
    解决 无用
    打赏 举报
  • 喵-见缝插针 2011-12-01 05:36

    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:

    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.

    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

      //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(''); });

    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.

    评论
    解决 无用
    打赏 举报
  • 狐狸.fox 2012-01-19 21:27

    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.

    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:

    /**
    * @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);
    }
    
    评论
    解决 无用
    打赏 举报
  • 程序go 2012-06-07 20:48

    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...

    See also:

    评论
    解决 无用
    打赏 举报
  • local-host 2012-06-07 20:55

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

    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.

    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

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

    Excerpt from the 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.

    ...

    评论
    解决 无用
    打赏 举报
  • 旧行李 2012-07-03 13:32

    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.

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

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

    Refer to:

    评论
    解决 无用
    打赏 举报
  • 程序go 2012-08-22 04:33
    var js = document.createElement("script");
    
    js.type = "text/javascript";
    js.src = jsFilePath;
    
    document.body.appendChild(js);
    
    评论
    解决 无用
    打赏 举报
  • 零零乙 2012-08-25 20:17

    Better use the jQuery way. To delay the ready event, first call $.holdReady(true). Example (source):

    $.holdReady(true);
    $.getScript("myplugin.js", function() {
        $.holdReady(false);
    });
    
    评论
    解决 无用
    打赏 举报
  • larry*wei 2013-03-24 19:32

    This should do:

    xhr = new XMLHttpRequest();
    xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
    xhr.send();
    eval(xhr.responseText);
    
    评论
    解决 无用
    打赏 举报
  • 七度&光 2013-04-12 16:34

    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.

    // ----- 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);
    };
    
    评论
    解决 无用
    打赏 举报
  • ℙℕℤℝ 2013-05-31 19:31

    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.

    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'.

    评论
    解决 无用
    打赏 举报
  • from.. 2013-07-13 21:44

    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.

    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.

    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:

    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(){}
        }
    };
    
    评论
    解决 无用
    打赏 举报
  • 三生石@ 2013-10-26 03:42

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

    (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);
    })();
    
    评论
    解决 无用
    打赏 举报
  • 程序go 2013-11-13 09:18

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

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

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

    $.getScript("another_script.js");
    
    评论
    解决 无用
    打赏 举报
  • 10.24 2013-11-22 18:40

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

    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.

    评论
    解决 无用
    打赏 举报
  • bug^君 2013-12-11 11:54

    Here is a synchronous version without 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.

    评论
    解决 无用
    打赏 举报
  • ~Onlooker 2014-03-14 04:40

    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.

    From the Mixture documentation on .mix files:

    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.

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

    // 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).

    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.

    UPDATE: Mixture is now free (offline).

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

    评论
    解决 无用
    打赏 举报
  • perhaps? 2015-01-01 08:58

    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.

    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.

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

    评论
    解决 无用
    打赏 举报
  • local-host 2015-01-11 20:19

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

    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.

    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.

    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.

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

    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.

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

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

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

    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.

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

    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 file3
    alert(f3obj); // "file3"
    alert(f2obj); // "file2"
    
    $(function(){
        // Use objects from file2 or file3 some more.
        alert(f3obj); //"file3docready"
        alert(f2obj); //"file2docready"
    });
    
    评论
    解决 无用
    打赏 举报
  • 三生石@ 2015-04-17 01:56

    Statement import is in 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;
    
    评论
    解决 无用
    打赏 举报
  • ~Onlooker 2015-07-08 02:41

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

    <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.

    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/.

    </div>
    
    评论
    解决 无用
    打赏 举报
  • ~Onlooker 2015-07-22 02:15

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

    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>
        <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.

    This saved my day. I hope this helps.

    评论
    解决 无用
    打赏 举报
  • YaoRaoLov 2015-07-24 06:53

    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:

    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:

    <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>
    
    评论
    解决 无用
    打赏 举报
  • MAO-EYE 2017-07-20 15:15

    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 );
      });
    }
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题