Come posso includere un file JavaScript in un altro file JavaScript?

C’è qualcosa in JavaScript simile a @import in CSS che ti consente di includere un file JavaScript all’interno di un altro file JavaScript?

Le vecchie versioni di JavaScript non avevano importato, incluso o richiesto, pertanto sono stati sviluppati molti approcci diversi a questo problema.

Ma le versioni recenti di JavaScript hanno standard come i moduli ES6 per importare i moduli, sebbene questo non sia ancora supportato dalla maggior parte dei browser. Molte persone che utilizzano moduli con applicazioni browser utilizzano strumenti di costruzione e / o transpilazione per rendere pratico l’uso della nuova syntax con funzioni come i moduli.

Moduli ES6

Nota che attualmente il supporto del browser per i moduli ES6 non è particolarmente grande, ma è in arrivo. Secondo questa risposta StackOverflow , sono supportati in Chrome 61, Firefox 54 (dietro l’impostazione dom.moduleScripts.enabled in about:config ) e MS Edge 16, con solo Safari 10.1 che fornisce supporto senza contrassegni.

Pertanto, al momento sarà ancora necessario utilizzare gli strumenti di compilazione e / o transposizione per JavaScript valido che verrà eseguito senza alcun obbligo per l’utente di utilizzare tali versioni del browser o abilitare eventuali flag.

Una volta che i moduli ES6 sono all’ordine del giorno, ecco come utilizzeresti:

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

Node.js richiede

Node.js sta attualmente utilizzando un sistema module.exports / require . Puoi usare babel per transpile se vuoi la syntax di import .

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

Esistono altri modi per JavaScript di includere contenuti JavaScript esterni nei browser che non richiedono il pre-elaborazione.

Caricamento AJAX

È ansible caricare uno script aggiuntivo con una chiamata AJAX e quindi utilizzare eval per eseguirlo. Questo è il modo più diretto, ma è limitato al tuo dominio a causa del modello di sicurezza sandbox JavaScript. L’uso di eval apre anche la porta a bug, hack e problemi di sicurezza.

Caricamento jQuery

La libreria jQuery fornisce funzionalità di caricamento in una riga :

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

Caricamento di script dinamici

È ansible aggiungere un tag script con l’URL dello script nell’HTML. Per evitare il sovraccarico di jQuery, questa è una soluzione ideale.

Lo script può anche risiedere su un server diverso. Inoltre, il browser valuta il codice. Il tag può essere inserito nella pagina web o inserito poco prima del chiusura.

Ecco un esempio di come potrebbe funzionare:

 function dynamicallyLoadScript(url) { var script = document.createElement("script"); // Make a script DOM node script.src = url; // Set it's 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) } 

Questa funzione aggiungerà un nuovo tag alla fine della sezione head della pagina, dove l'attributo src è impostato sull'URL che viene assegnato alla funzione come primo parametro.

Entrambe queste soluzioni sono discusse e illustrate in JavaScript Madness: Dynamic Script Loading .

Rilevare quando lo script è stato eseguito

Ora, c'è un grosso problema che devi conoscere. Ciò implica che il codice venga caricato in remoto . I moderni browser Web caricheranno il file e continueranno a eseguire lo script corrente perché caricano tutto in modo asincrono per migliorare le prestazioni. (Questo vale sia per il metodo jQuery che per il metodo di caricamento dinamico degli script manuale).

Significa che se si utilizzano questi trucchi direttamente, non sarà ansible utilizzare il codice appena caricato la riga successiva dopo aver chiesto di caricarlo , perché verrà ancora caricato.

Ad esempio: my_lovely_script.js contiene 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 

Quindi ricarichi la pagina colpendo F5 . E funziona! Confondere ...

Quindi cosa fare a riguardo?

Bene, puoi usare l'hack che l'autore suggerisce nel link che ti ho dato. In sintesi, per le persone di fretta, utilizza un evento per eseguire una funzione di callback quando lo script viene caricato. Quindi puoi inserire tutto il codice usando la libreria remota nella funzione di callback. Per esempio:

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

Quindi scrivi il codice che vuoi usare DOPO che lo script è caricato in una funzione lambda :

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

Quindi esegui tutto ciò:

 loadScript("my_lovely_script.js", myPrettyCode); 

Nota che lo script può essere eseguito dopo che il DOM è stato caricato, o prima, a seconda del browser e se hai incluso la riga script.async = false; . C'è un ottimo articolo sul caricamento di Javascript in generale che ne discute.

Fusione codice sorgente / preelaborazione

Come menzionato all'inizio di questa risposta, molti sviluppatori ora usano strumenti di compilazione / transpilazione come WebPack, Babel o Gulp nei loro progetti, consentendo loro di usare meglio la syntax e i moduli di supporto, combinare file, minificare, ecc.

Se qualcuno sta cercando qualcosa di più avanzato, prova RequireJS . Otterrai vantaggi aggiuntivi come la gestione delle dipendenze, una maggiore concorrenza ed evitare la duplicazione (ovvero, recuperare uno script più volte).

È ansible scrivere i file JavaScript in “moduli” e quindi fare riferimento a essi come dipendenze in altri script. Oppure puoi usare RequireJS come una semplice soluzione “vai a prendere questo script”.

Esempio:

Definisci le dipendenze come moduli:

alcuni-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 è il file JavaScript “principale” che dipende da some-dependency.js

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

Estratto dal README di GitHub :

RequireJS carica semplici file JavaScript e moduli più definiti. È ottimizzato per l’uso in-browser, incluso in un Web Worker, ma può essere utilizzato in altri ambienti JavaScript, come Rhino e Node. Implementa l’API del modulo asincrono.

RequireJS utilizza semplici tag di script per caricare moduli / file, quindi dovrebbe consentire un facile debug. Può essere utilizzato semplicemente per caricare i file JavaScript esistenti, in modo da poterlo aggiungere al progetto esistente senza dover riscrivere i file JavaScript.

In realtà esiste un modo per caricare un file JavaScript non in modo asincrono, quindi è ansible utilizzare le funzioni incluse nel file appena caricato subito dopo averlo caricato e penso che funzioni in tutti i browser.

Devi usare jQuery.append() sull’elemento della tua pagina, cioè:

 $("head").append(''); 

Tuttavia, questo metodo ha anche un problema: se si verifica un errore nel file JavaScript importato, Firebug (e anche Firefox Error Console e Chrome Developer Tools ) riporteranno la sua posizione in modo errato, il che è un grosso problema se usi Firebug per tracciare Errori JavaScript molto giù (io faccio). Firebug semplicemente non conosce il nuovo file caricato per qualche motivo, quindi se si verifica un errore in quel file, segnala che si è verificato nel tuo file HTML principale, e avrai difficoltà a scoprire il vero motivo dell’errore.

Ma se questo non è un problema per te, allora questo metodo dovrebbe funzionare.

Ho effettivamente scritto un plugin jQuery chiamato $ .import_js () che usa questo metodo:

 (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(''); import_js_imported.push(script); } } }); })(jQuery); 

Quindi tutto ciò che devi fare per importare JavaScript è:

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

Ho anche fatto un semplice test per questo in Esempio .

Include un file main.js nell’HTML principale e quindi lo script in main.js utilizza $.import_js() per importare un file aggiuntivo chiamato included.js , che definisce questa funzione:

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

E subito dopo incluso included.js , viene chiamata la funzione hello() e ottieni l’avviso.

(Questa risposta è in risposta al commento di e-satis).

Un altro modo, a mio avviso molto più pulito, consiste nel creare una richiesta Ajax sincrona anziché utilizzare un tag . Che è anche il modo in cui gestisce Node.js include.

Ecco un esempio di 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); } }); } 

Puoi quindi utilizzarlo nel tuo codice come di solito utilizzi un include:

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

E essere in grado di chiamare una funzione dallo script richiesto nella riga successiva:

 subscript.doSomethingCool(); 

C’è una buona notizia per te. Molto presto sarai in grado di caricare facilmente il codice JavaScript. Diventerà un modo standard di importare moduli di codice JavaScript e farà parte del core JavaScript stesso.

Devi semplicemente scrivere import cond from 'cond.js'; per caricare una macro denominata cond da un file cond.js

Quindi non devi fare affidamento su alcun framework JavaScript né devi fare esplicitamente chiamate Ajax .

Fare riferimento a:

  • Risoluzione del modulo statico

  • Caricatori di moduli

È ansible generare dynamicmente un tag JavaScript e aggiungerlo a un documento HTML all’interno di un altro codice JavaScript. Questo caricherà il file JavaScript mirato.

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

L’ import istruzioni è in ECMAScript 6.

Sintassi

 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; 

Forse puoi usare questa funzione che ho trovato su questa pagina Come posso includere un file JavaScript in un file 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) } 

Ecco una versione sincrona senza 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); } 

Si noti che per ottenere questo cross-domain funzionante, il server dovrà impostare l'intestazione allow-origin nella sua risposta.

Ho appena scritto questo codice JavaScript (utilizzando Prototype per la manipolazione 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); } }); })(); 

Uso:

    

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

Ecco la versione generalizzata di come Facebook lo fa per il loro pulsante Mi piace onnipresente:

  

Se si desidera in puro JavaScript, è ansible utilizzare document.write .

 document.write(''); 

Se si utilizza la libreria jQuery, è ansible utilizzare il metodo $.getScript .

 $.getScript("another_script.js"); 

Puoi anche assemblare i tuoi script usando PHP :

File main.js.php :

  // Main JavaScript code goes here 

La maggior parte delle soluzioni mostrate qui implica un caricamento dinamico. Stavo cercando invece un compilatore che assemblasse tutti i file dipendenti in un singolo file di output. Gli stessi preprocess di Less / Sass si occupano della regola @import CSS. Poiché non ho trovato nulla di decente di questo genere, ho scritto un semplice strumento per risolvere il problema.

Quindi ecco il compilatore, https://github.com/dsheiko/jsic , che sostituisce $import("file-path") con il contenuto del file richiesto in modo sicuro. Ecco il corrispondente plugin Grunt : https://github.com/dsheiko/grunt-jsic .

Nel ramo master di jQuery, concatenano semplicemente i file di origine atomici in un singolo iniziando con intro.js e terminando con outtro.js . Questo non mi va bene in quanto non fornisce alcuna flessibilità sulla progettazione del codice sorgente. Guarda come funziona con jsic:

src / main.js

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

src / Form / Input / Tel.js

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

Ora possiamo eseguire il compilatore:

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

E ottieni il file combinato

build / main.js

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

Questo dovrebbe fare:

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

Se la tua intenzione di caricare il file JavaScript sta utilizzando le funzioni del file importato / incluso , puoi anche definire un object globale e impostare le funzioni come oggetti. Per esempio:

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

Devi solo fare attenzione quando includi script in un file HTML. L’ordine dovrebbe essere come in seguito:

       

O piuttosto che includere in fase di esecuzione, utilizzare uno script per concatenare prima del caricamento.

Io uso pignoni (non so se ce ne sono altri). Si crea il codice JavaScript in file separati e si includono i commenti elaborati dal motore Sprockets come include. Per lo sviluppo è ansible includere i file in sequenza, quindi per la produzione per unirli …

Guarda anche:

  • Presentazione di pignoni: gestione delle dipendenze JavaScript e concatenazione

Nel caso in cui si utilizzino Web Worker e si desideri includere script aggiuntivi nell’ambito del worker, le altre risposte fornite sull’aggiunta di script al tag head , ecc. Non funzioneranno per voi.

Fortunatamente, i lavoratori Web hanno una propria funzione importScripts che è una funzione globale nell’ambito di Web Worker, nativa per il browser stesso poiché fa parte delle specifiche .

In alternativa, RequireJS può anche gestire gli script inclusi in un Web Worker (probabilmente chiamando importScripts stesso, ma con qualche altra funzionalità utile).

Ho avuto un problema semplice, ma ero sconcertato dalle risposte a questa domanda.

Ho dovuto usare una variabile (myVar1) definita in un file JavaScript (myvariables.js) in un altro file JavaScript (main.js).

Per questo ho fatto come di seguito:

Caricato il codice JavaScript nel file HTML, nell’ordine corretto, prima myvariables.js, poi main.js:

        

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

Come hai visto, avevo usato una variabile in un file JavaScript in un altro file JavaScript, ma non avevo bisogno di includerne uno in un altro. Avevo solo bisogno di assicurarmi che il primo file JavaScript caricato prima del secondo file JavaScript e, le prime variabili del file JavaScript fossero accessibili nel secondo file JavaScript, automaticamente.

Questo mi ha salvato la giornata. Spero che aiuti.

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

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

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

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

This script will add a JavaScript file to the top of any other 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); })(); 

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 .

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

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:

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.

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

Esempio:

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.

Soluzione:

 $.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(""); // 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; } }); 

Uso:

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

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  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:  */ function imports(file) { var fileName = file.substr(file.lastIndexOf('.') + 1, file.length); // Convert PascalCase name to underscore_separated_name var regex = new RegExp(/([AZ])/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); } 

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

 $.holdReady(true); $.getScript("myplugin.js", function() { $.holdReady(false); });