import js - Come posso includere un file JavaScript in un altro file JavaScript?



another load (25)

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

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

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

$.getScript("another_script.js");

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


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

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

Se funziona per Facebook, funzionerà per te.

Il motivo per cui cerchiamo il primo elemento di script posto di head o body è perché alcuni browser non ne creano uno se mancano, ma abbiamo garantito un elemento di script - questo. Maggiori informazioni su http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ .


In realtà esiste un modo per caricare un file JavaScript non in modo asincrono, quindi è possibile 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 <head> della tua pagina, cioè:

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

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('<script type="text/javascript" src="' + script + '"></script>');
                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 Example .

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


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;

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:

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

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 questo possa essere d'aiuto.


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


Ci sono molte potenziali risposte a questa domanda. La mia risposta è ovviamente basata su un numero di essi. Questo è quello che ho finito dopo aver letto tutte le risposte.

Il problema con $.getScripte davvero qualsiasi altra soluzione che richiede un callback quando il caricamento è completo è che se si hanno più file che li usano e dipendono l'uno dall'altro non si ha più modo di sapere quando tutti gli script sono stati caricati (una volta che sono nidificati in più file).

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

Hai ragione quando dici che puoi specificare Ajax per l'esecuzione in modo sincrono o utilizzare XMLHttpRequest , ma sembra che la tendenza attuale sia la deprecazione delle richieste sincrone, quindi potresti non ottenere il supporto completo del browser ora o in futuro.

Si può provare a usare $.whenper controllare un array di oggetti posticipati, ma ora lo si sta facendo in ogni file e il file2 verrà considerato caricato non appena $.whenviene eseguito non quando viene eseguito il callback, quindi file1 continua a essere eseguito prima del caricamento di file3 . Questo ha ancora lo stesso problema.

Ho deciso di andare indietro invece che in avanti. Grazie document.writeln. So che è un tabù, ma finché viene usato correttamente questo funziona bene. Si finisce con il codice che può essere debug facilmente, mostra nel DOM correttamente e può garantire l'ordine in cui le dipendenze sono caricate correttamente.

Ovviamente puoi usare $ ("body"). Append (), ma non puoi più eseguire il debug più correttamente.

NOTA: è necessario utilizzarlo solo mentre la pagina si sta caricando, altrimenti si ottiene una schermata vuota. In altre parole, posiziona sempre questo prima / all'esterno di document.ready . Non ho provato a usare questo dopo che la pagina è stata caricata in un evento click o qualcosa del genere, ma sono abbastanza sicuro che fallirà.

Mi è piaciuta l'idea di estendere jQuery, ma ovviamente non è necessario.

Prima di chiamare document.writeln, controlla che lo script non sia già stato caricato valutando tutti gli elementi dello script.

Suppongo che uno script non sia completamente eseguito fino a quando il suo document.readyevento non è stato eseguito. (So ​​che l'uso document.readynon è richiesto, ma molte persone lo usano, e gestirlo è una salvaguardia.)

Quando vengono caricati i file aggiuntivi, i document.readycallback verranno eseguiti nell'ordine sbagliato. Per risolvere questo problema quando uno script viene effettivamente caricato, lo script che lo ha importato viene reimportato e l'esecuzione viene interrotta. Questo fa sì che il file di origine abbia ora la sua document.readycallback eseguita dopo qualsiasi da qualsiasi script che importa.

Invece di questo approccio, potresti provare a modificare il jQuery readyList, ma questa sembrava una soluzione peggiore.

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

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

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

costruire / main.js

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

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

Io uso Sprockets (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 è possibile includere i file in sequenza, quindi per la produzione per unirli ...

Guarda anche:


Ho creato una funzione che ti permetterà di usare una verbosità simile a C # / Java per includere un file JavaScript. L'ho testato un po 'anche all'interno di un altro file JavaScript e sembra funzionare. Richiede jQuery anche se per un po 'di "magia" alla fine.

Ho messo questo codice in un file alla radice della mia directory di script (l'ho chiamato global.js, ma puoi usare quello che vuoi. A meno che non mi sbagli e jQuery dovrebbe essere l'unico script richiesto su una determinata pagina. è in gran parte non testata al di là di qualche utilizzo di base, quindi non ci possono essere problemi con il modo in cui ho fatto, utilizzare a proprio rischio yadda yadda non sono responsabile se si avvita nulla su 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);
}

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

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

...


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

Ma dal 2015 (ES6), JavaScript ha avuto lo standard dei moduli ES6 per importare i moduli in Node.js, che è anche supportato dalla maggior parte dei browser moderni .

Per compatibilità con i browser più vecchi, è possibile utilizzare strumenti di build e / o transpilation .

Moduli ES6

I moduli ECMAScript (ES6) sono stati supportati in Node.js dalla v8.5, con il --experimental-modules . Tutti i file coinvolti devono avere l'estensione .mjs .

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

Moduli ECMAScript nei browser

I browser hanno supportato il caricamento diretto dei moduli ECMAScript (non sono richiesti strumenti come Webpack) since Safari 10.1, Chrome 61, Firefox 60 e Edge 16. Controlla il supporto corrente su 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);
}

Maggiori informazioni su: since

Importazioni dinamiche nei browser

Le importazioni dinamiche consentono allo script di caricare altri script in base alle esigenze:

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

Maggiori informazioni su: https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js richiede

Il vecchio stile di importazione dei moduli, ancora ampiamente utilizzato in Node.js, è il sistema module.exports/require .

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

È possibile 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

È possibile 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 <script> può essere inserito nella pagina web <head> o inserito poco prima del </body> chiusura.

Ecco un esempio di come potrebbe funzionare:

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

Questa funzione aggiungerà un nuovo tag <script> 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à possibile 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 usano nei loro progetti strumenti di costruzione / transpilazione come Parcel, Webpack o Babel, consentendo loro di utilizzare la sintassi imminente di JavaScript, fornire la retrocompatibilità per i browser più vecchi, combinare file, minificare, eseguire la divisione del codice ecc.


var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

Questo script aggiungerà un file JavaScript all'inizio di qualsiasi altro <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);
})();

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:


C'è anche Head.js . È molto facile da gestire:

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

Come vedi, è più facile di Require.js e conveniente come il $.getScriptmetodo di jQuery . Ha anche alcune funzionalità avanzate, come il caricamento condizionale, il rilevamento delle funzioni e molto altro .


Se la tua intenzione di caricare il file JavaScript sta utilizzando le funzioni del file importato / incluso , puoi anche definire un oggetto 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:

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

Meglio usare il modo jQuery . Per ritardare l'evento pronto, prima chiamare $.holdReady(true). Esempio ( source ):

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

Ho appena scritto questo codice JavaScript (utilizzando Prototype per DOM 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:

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


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.


Sono arrivato a questa domanda perché stavo cercando un modo semplice per mantenere una collezione di utili plugin JavaScript. Dopo aver visto alcune delle soluzioni qui, ho trovato questo:

  1. Imposta un file chiamato "plugins.js" (o extensions.js o cosa hai). Conserva i tuoi file plugin insieme a quel file master.

  2. plugins.js avrà un array chiamato "pluginNames []" che verrà ripetuto su each (), quindi aggiungerà un tag alla testa per ogni plugin

    // imposta la matrice da aggiornare quando aggiungiamo o rimuoviamo i file plugin var pluginNames = ["lettering", "fittext", "butterjam", ecc.]; // un tag script per ogni plugin $ .each (pluginNames, function () {$ ('head'). append ('');});

  3. chiama manualmente solo l'unico file nella tua testa:
    <script src="js/plugins/plugins.js"></script>

Ho scoperto che anche se tutti i plug-in venivano rilasciati nel tag head come dovrebbero, non venivano sempre eseguiti dal browser quando si fa clic sulla pagina o si aggiorna.

Ho scoperto che è più affidabile scrivere solo i tag script in un PHP include. Devi solo scriverlo una volta e questo è altrettanto utile che chiamare il plugin usando JavaScript.


Nel linguaggio moderno sarebbe

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

Un altro modo, a mio avviso molto più pulito, consiste nel creare una richiesta Ajax sincrona anziché utilizzare un tag <script> . 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(); 

Ho scritto un semplice modulo che automatizza il lavoro di importazione / inclusi gli script dei moduli in JavaScript. Per una spiegazione dettagliata del codice, fare riferimento al post del blog JavaScript richiede / importa / include i moduli .

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

Ok, parlando con un bambino di 6 anni, potrei usare le seguenti associazioni.

Immagina: stai giocando con i tuoi fratellini e sorelline in tutta la casa, e ti muovi con i tuoi giocattoli e ne porti alcuni nella stanza di tuo fratello maggiore. Dopo un po 'tuo fratello tornò dalla scuola e andò nella sua stanza, e lui vi rinchiuse, così ora non potevi accedere ai giocattoli lasciati lì in modo diretto. Ma potresti bussare alla porta e chiedere a tuo fratello quei giocattoli. Questo si chiama chiusura del giocattolo ; tuo fratello ha inventato per te, e ora è nel campo di applicazione esterno .

Confrontati con una situazione in cui una porta è stata bloccata da una brutta copia e nessuno all'interno (esecuzione di una funzione generale), poi un incendio locale si è verificato e ha bruciato la stanza (garbage collector: D), e poi una nuova stanza è stata costruita e ora puoi andartene un altro giocattolo (nuova istanza di funzione), ma mai gli stessi giocattoli che sono stati lasciati nella prima istanza della stanza.

Per un bambino avanzato vorrei mettere qualcosa come il seguente. Non è perfetto, ma ti fa sentire quello che è:

function playingInBrothersRoom (withToys) {
  // We closure toys which we played in the brother's room. When he come back and lock the door
  // your brother is supposed to be into the outer [[scope]] object now. Thanks god you could communicate with him.
  var closureToys = withToys || [],
      returnToy, countIt, toy; // Just another closure helpers, for brother's inner use.

  var brotherGivesToyBack = function (toy) {
    // New request. There is not yet closureToys on brother's hand yet. Give him a time.
    returnToy = null;
    if (toy && closureToys.length > 0) { // If we ask for a specific toy, the brother is going to search for it.

      for ( countIt = closureToys.length; countIt; countIt--) {
        if (closureToys[countIt - 1] == toy) {
          returnToy = 'Take your ' + closureToys.splice(countIt - 1, 1) + ', little boy!';
          break;
        }
      }
      returnToy = returnToy || 'Hey, I could not find any ' + toy + ' here. Look for it in another room.';
    }
    else if (closureToys.length > 0) { // Otherwise, just give back everything he has in the room.
      returnToy = 'Behold! ' + closureToys.join(', ') + '.';
      closureToys = [];
    }
    else {
      returnToy = 'Hey, lil shrimp, I gave you everything!';
    }
    console.log(returnToy);
  }
  return brotherGivesToyBack;
}
// You are playing in the house, including the brother's room.
var toys = ['teddybear', 'car', 'jumpingrope'],
    askBrotherForClosuredToy = playingInBrothersRoom(toys);

// The door is locked, and the brother came from the school. You could not cheat and take it out directly.
console.log(askBrotherForClosuredToy.closureToys); // Undefined

// But you could ask your brother politely, to give it back.
askBrotherForClosuredToy('teddybear'); // Hooray, here it is, teddybear
askBrotherForClosuredToy('ball'); // The brother would not be able to find it.
askBrotherForClosuredToy(); // The brother gives you all the rest
askBrotherForClosuredToy(); // Nothing left in there

Come puoi vedere, i giocattoli lasciati nella stanza sono ancora accessibili tramite il fratello e non importa se la stanza è chiusa. Ecco un jsbin per giocarci.





javascript file import include