1

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.

3
  • So the problem is there are name clashes between the multiple files - multiple function xyzs? Is modifying them really that bad - you're worried about introducing errors, or keeping compatible with upstream? Could you mechanically do the rename, e.g. sed or with a minifying tool somehow? Commented Jan 10, 2012 at 1:06
  • I'm thinking along the lines of a minifying tool or macro preprocessor also. How many xyzs do you have to deal with? And, is it really the best idea to put all this stuff in one file if only part of it is going to be executed on any given page? Commented Jan 10, 2012 at 1:28
  • Well, the idea is that depending on the page, and the context, we have too many files loading. Somewhere around 100 various resources (including css/images). So, in an attempt to cut down this number, we're trying to combine some files that get used often. In this case, some are libraries, and some are our in house code. Up until this point we had not worried about placing function xyz() {} in the global scope. With the new combined file, if (false) { function xyz() {} } ends up in the global scope, so we figured wrapping it in var foo = function() { function xyz() {} }; if (false) { foo(); } Commented Jan 10, 2012 at 15:30

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

5 Comments

This is a good solution if we were writing all of the code from the beginning, but again the main focus of the question is that if it is possible to explicitly place a nested function in the global scope.
Ah, I see. Please see my edit - I think this addresses what you're going for.
Thanks. That seems to work. From what I can tell, I think this is the best we're going to get. I can live with this, but I was really hoping for some sort of clever wrap. You can see how I'd like to be able to do something like (function() { function xyz() { } }).apply(window, []); as a sneaky solution.
Your apply trick only sets the value of this within the internal function - so you could do (function() { this.xyz = function() { } }).apply(window, []) instead of my version. But my version is probably more legible, and will compress better.
Actually, your version is also better with regards to my requirements where I don't want to edit the bulk of the file. In my situation, I'd prefer to add a few lines at the end instead of altering the combined code. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.