0

I am writing a JS file that will be included as an external script in other pages using the HTML <script> tag.

I want to make certain parts of the script optionally configurable by setting certain global variables. For example, imagine a script like this:

//external.js
var show = false;
$(function() {
    if(show) alert('show');
    else alert('no show');
});

//test.html
<script src="external.js"></script>
<script>show = true</script>

So I define the variable and its default value in the external script, but then overwrite it in the HTML file before displaying the alert on document ready.

Now this works fine so far, however it falls apart once I try to load external.js asynchronously using the async attribute. This is because now the external script may actually become loaded after the show = true line, meaning it will overwrite the custom value again with the default.

My current solution to this is something like this, which works but seems unnecessarily complicated:

//external.js
var show = false;
$(function() {
    if ( typeof my_init == 'function' ) { my_init(); }
    if(show) alert('show');
    else alert('no show');
});

//test.html
<script async src="external.js"></script>
<script>function my_init() { show = true }</script>

Is there a better way to do things?

Nils
  • 1,936
  • 3
  • 27
  • 42
  • Read this and you will get things right: http://stackoverflow.com/questions/2421911/what-is-the-purpose-of-wrapping-whole-javascript-files-in-anonymous-functions-li – Asons Mar 04 '14 at 18:30
  • Hmm, I'm not sure how this would help. Doesn't this do pretty much the opposite of what I want to accomplish? – Nils Mar 04 '14 at 18:32
  • you should set the global value before you include the external js... Otherwise the external js might execute before the global value has been set. – Kevin B Mar 04 '14 at 18:33
  • You should avoid global variables, as they can complicate things later – Asons Mar 04 '14 at 18:34
  • Kevin: In that case it would just get overwritten once the first line of the external JS is executed, wouldn't it? I presume I could check for whether the variable already exists before declaring it in the external.js, but that feels more or less as messy as my current approach. – Nils Mar 04 '14 at 18:36
  • PellePenna: I agree, but this is unfortunately not an easy change to make. – Nils Mar 04 '14 at 18:37
  • It might be easier than you think. Check this simple wrapper: http://jsfiddle.net/HLp2v/ – Asons Mar 04 '14 at 18:38
  • Updated it again to this: http://jsfiddle.net/HLp2v/1/ – Asons Mar 04 '14 at 18:41
  • @Nils Yes, it would, unless you code the first line of the external js to first look for an existing value. – Kevin B Mar 04 '14 at 18:41

2 Answers2

0

The typical way to handle something like this is with a configuration object. Something like:

(function (config) {
    $(function () {
        if (config.show) alert('show');
        else alert('no show');
    });
})(window.config || (config = { show: false }));

And now in your other script you do this:

config = { show: true }

What this does is use the provided config object if one is defined, else it uses a default with show set to false.

However, better would be to wrap this all up as a module rather than using globals.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

Law of Demeter - Code components should only communicate with their direct relations (e.g. classes that they inherit from, objects that they contain, objects passed by argument, etc.)

You should be passing a config object as a parameter.

Michael Benjamin
  • 2,895
  • 1
  • 16
  • 18