3

I have a file bg.js whose contents is simply an IIFE. I'd like to load this file/call the function in from another function in another file. Since the IIFE is anonymous (it is, right?) I can't call it by name. It seems I have to load the entire file so it executes immediately.

I've done searching and found many tutorials and documents about what an IIFE is, but nowhere had I seen how to execute one from another scope.

How do I call/load a javascript file that is an IIFE from another javascript file?

More Information The IIFE is loaded in the footer of my page. When I click a link to navigate, the header and footer scripts are not executed. The IIFE in the footer is responsible for setting the background image, so I need to get that function to execute in my perPageBindings()

What I think I need to do is invoke the IIFE from another function in the body which is being executed in perPageBindings()

Edit for clarity There are two options I am considering:

  1. Simply move the script tag to the body from the footer; or
  2. Give the IIFE a name so it is no longer anonymous and then call that named function from elsewhere

If 2 is a viable option then I think I will create a new question about converting and IIFE to a named function.

Ian R. O'Brien
  • 6,682
  • 9
  • 45
  • 73
  • Please let me know if I need to post a code sample. – Ian R. O'Brien Oct 09 '15 at 15:05
  • 2
    You can use `$.getScript` to load the js file globally and execute it. – gen_Eric Oct 09 '15 at 15:09
  • 7
    by definition an IIFE is Immediately invoked - it makes no sense to be able to "call it from another file". – Jamiec Oct 09 '15 at 15:09
  • Create a script tag, set the source of the tag to your file containing the IIFE, use the script tag to fetch the script. The IIFE will execute then. But you won't be able to use anything inside the IIFE unless you return an interface from that IIFE the other script can use. – Shilly Oct 09 '15 at 15:10
  • JavaScript doesn't have an "include" function. You *can* to load the file via AJAX and run it in the *current* scope, but that would use `eval()` which is a bad idea. – gen_Eric Oct 09 '15 at 15:10
  • 1
    This sounds like an XY problem. Need more details about what the IIFE does and what you want it to do and in what sequence – charlietfl Oct 09 '15 at 15:10
  • 2
    I think if you include some code and your actual intent, you might find you get an answer that gives you a better way/alternative – Jamiec Oct 09 '15 at 15:11
  • I added some more information but I will have to wait until tonight to post the code since I don't have access to it now. – Ian R. O'Brien Oct 09 '15 at 15:13
  • 1
    Restructure the IIFE so it is a function you can call when needed – charlietfl Oct 09 '15 at 15:16
  • 1
    Force the script tag containing the IIFE to reload by removing it and re-adding it. This will cause the IIFE to be executed again. http://stackoverflow.com/questions/9642205/how-to-force-a-script-reload-and-re-execute – Preston S Oct 09 '15 at 15:29

3 Answers3

3

If you want to access something within that script, a function or a property, after it has been anonymously invoked, you'll need to expose some of the internals of that function to something that is accessible from global scope.

I'm not saying that you must have your function put a variable into global scope, although that is what many libraries do and is one of the paths that UMD follows if a CommonJS or AMD environment is not available.

You should look into the Revealing Module Pattern for a better perspective.

Consider the following code snippet:

(function(global){
    /*
     * This variable will stay "private" 
     * because it is scoped to the IIF
     */
    var someProp = "Hello World";

    /*
     * This property is effectively exposed 
     * because it is accessible through 
     * myLib.foxtrot below
     */
    var someOtherProp = "Hello to you too";

    var myLib = {
        foo: "bar",
        fiz: true,
        buzz: 1,
        foxtrot: someOtherProp
    };

    /*
     * myLib is now accessible through the 
     * global that we passed to the IIF below
     * at the point of calling with "window"
     */
    global.myLib = myLib;

}(window));
zero298
  • 25,467
  • 10
  • 75
  • 100
2

Seems like you want to define this function some where that makes it reusable. If you want to invoke from the footer wrap the reusable function call in an IIFE. That way its immediately invoked in the footer and calls your function but you can also call this function elsewhere.

Example:

JS:

function setBackground () {
    // sets background and can be called whenever
}

HTML:

<footer>
    <script>
        (function () {
            setBackground();
        } ());
    <script>
</footer>
AtheistP3ace
  • 9,611
  • 12
  • 43
  • 43
0

There is no need to import the global to an IIFE

instead of coding

(function(global){
    //...
    global.myLib = myLib;
}(window));

you can code directly

{
    window.myLib = {
        //...
    };
}

I add IIFE always to a namespace, so it's easy referable.

var app = {};
{
    app.myLibrary = {
        log: (str)  =>  window.console.log(str),
    };
    // is executed immediately
    window.console.log(`myLibrary = ${app.myLibrary}`);
}

{
    app.external = {
        call: (str) => app.myLibrary.log(str),
    };
    // is executed immediately
    window.console.log(`external = ${app.external}`);
}
// is easy referable
app.external.call('Hello World!');
BzB
  • 41
  • 5