Dustin Graham
Dustin Graham

Reputation: 2086

Can a nested function be placed in the global scope of Javascript?

I have a situation where I'm trying to consolidate several Javascript files into one, and conditionally apply them. I don't want to modify the actual files. Is there a way I can wrap these files and call them on demand?

The catch is, some of these files have function xyz() {} in them. So, wrapping them with if (false) { function xyz() {} } makes bad things happen.

For example, if this is my code...

if (includeFile) {
    /* The file */
    function foo() {}
    /* The file */
}

The problem becomes that Chrome will see foo() and place it in the global scope even if includeFile is false.

The easy solution would be to modify it to be var foo = function() {} but I can't modify these files.

I also have a general concern about running eval() on these functions since they are fairly huge. (Think jQuery wrapped in a function. If this isn't a problem then maybe eval is the answer?)

I was hoping I could nest functions and pass window in as the scope, but tried it on jsFiddle and it didn't seem to work.

(function() {
    function foo() {
        alert('it works');
    }
}).apply(window, []);

foo();

There are a few similar questions. But, none addressed the same situation that I have. Thanks.

Upvotes: 1

Views: 530

Answers (1)

nrabinowitz
nrabinowitz

Reputation: 55688

Have you considered using a library like require.js? There are several libraries out there that can do this for you in a more elegant fashion.

If you don't want a dependency-loading library, but you're using jQuery or some similar library, you can load scripts conditionally using an AJAX request (in jQuery, you'd use the script dataType). This is far better than a simple eval(), but less robust when you're trying to manage a series of dependencies.

Another option here, if you want to simply concatenate everything, is to wrap each file in an anonymous function and then assign the necessary elements to the window object, placing them in the global scope:

(function(window) {

    /* file 1 here */
    function xyz() {
        // etc ...
    }
    /* end file 1 */

    // now selectively choose what you want to be
    // in the global scope
    window.xyz = xyz;

}(window));

xyz();

This requires more work for you, however, to identify what you want to be available globally. Note that it's note necessary to pass window in as an argument to the anonymous function, but it's not a bad idea if you're going to be be referring to it multiple times (this speeds up references and allows for variable-name munging during code compression).

Upvotes: 2

Related Questions