1

What is the simplest way to put a variable in one js file in the scope of another js file. The question has been asked before, and answers given. But I'm unsatisfied because (1) The explanations were not simple to me and (2) The solutions were not simple to me. One answer was "As long as the global variable has been put into global scope before it is called by the external script." The OP asked "how do I put the global variable into global scope?", and there was no direct answer.

So, I have:

test1.js

var a = true;

test2.js

alert("a is " + a);
console.log("a is " + a);

and

test.html

<html>
  <body>
    <h1>Test</h1>
  </body>

  <script src="js/test1.js"></script>
  <script src="js/test2.js"></script>
</html>

No alert appears, and the console logs ReferenceError: a is not defined.

What is the simplest way to make the variable a available in test2.js?

Community
  • 1
  • 1
abalter
  • 9,663
  • 17
  • 90
  • 145
  • 1
    Can you describe the environment (server, client?), loading order / method (i.e. script tags, ajax, etc.?) of test1.js and test2.js, etc? – jdphenix Apr 16 '15 at 23:46
  • 1
    You `var a = true` in test1.js must not be at the top level scope (e.g. it must be inside some function). If this is a server side node.js file, then no variables defined in modules default to the global scope. If it's a regular browser-side JS file then all variables at the top level of the file default to the global scope. – jfriend00 Apr 16 '15 at 23:48
  • I edited to show the html file. It's on a bluehost server. – abalter Apr 16 '15 at 23:49
  • What you show will not generate that error if you are successfully loading both test1.js and test2.js in that order so there is clearly something else wrong in your setup. Are you 200% sure there are no script errors or loading errors anywhere? – jfriend00 Apr 16 '15 at 23:50
  • I produce expected behavior with `index.html` at `.` and `test1.js` and `test2.js` at `./js` with Internet Explorer, Firefox, and Chrome. I agree with @jfriend00, the `var a` statement has got to be in the scope of some function or something isn't loading – jdphenix Apr 16 '15 at 23:51
  • @jdphenix - or the other possibility is that `js/test1.js` isn't loading properly. – jfriend00 Apr 16 '15 at 23:52
  • @jfriend00 Indeed, I edited in "or something isn't loading" a split second after I had clicker's remorse about the Add Comment button :) – jdphenix Apr 16 '15 at 23:53
  • The console output I gave is the ONLY thing I get. – abalter Apr 16 '15 at 23:53
  • Please show the ENTIRE `test1.js` and `test2.js` files in your post and install a `console.log("test1.js start")` at the top of test1.js, a `console.log("test1.js end")` at the end of test1.js and a `console.log("test2.js start")` at the top of test2.js and a `console.log("test2.js end")` at the end of test2.js and then see what outputs. – jfriend00 Apr 16 '15 at 23:56
  • Those are the entire files. I'll add the console logs to verify the files are loading. – abalter Apr 17 '15 at 00:02
  • Can you confirm your project that exhibits the behavior you've described is *exactly* like this one? https://github.com/jdphenix/so29687802 – jdphenix Apr 17 '15 at 00:04
  • test2.js is running, but not test1.js – abalter Apr 17 '15 at 00:04
  • Does the browser console report any errors (404, 403, etc.?) – jdphenix Apr 17 '15 at 00:05
  • @jdphenix, I'll be danged if those files don't look identical to my old eyes, and [yet, this](http://arielbalter.com/jdphenix/). – abalter Apr 17 '15 at 00:09
  • No. No errors. [http://arielbalter.com/gators/test.html](http://arielbalter.com/gators/test.html) I'm worried you are going to find a syntax error on my part. And then I will feel like a complete dork. – abalter Apr 17 '15 at 00:14
  • 1
    @abalter in that link above, `test1.js` is a blank file... http://arielbalter.com/gators/js/test1.js – Maverick Apr 17 '15 at 00:15
  • @Maverick that is soooo strange. http://imgur.com/gallery/plmDlWY/new – abalter Apr 17 '15 at 00:31
  • So, I opened test1.js using winscp and edited it. The edits did show up in Cloud9. Now "it" works. So that was it all along? Some glitch in my editor not actually saving to the file what it showed? This would indicate that the answer is that a variable declared as a `var` in one file is available in another file as long as the first file is loaded first. Is that wrong? – abalter Apr 17 '15 at 01:15
  • @abalter, I added an answer below explaining it (mostly for the benefit of future googlers :)). – Maverick Apr 17 '15 at 01:39
  • Given the solution, the question should be closed or deleted as it offers no ongoing benefit to the community as it was simply an intended blank file. I've vote to close as not reproducible as posted. – jfriend00 Apr 17 '15 at 02:37
  • @abalter - You can delete it yourself. There's a "delete" link right under the question. – jfriend00 Apr 17 '15 at 04:44
  • Ok. Just want to thank the folks who helped me figure out what was going on! I'll delete it in the morning (here) after folks get to read this! – abalter Apr 17 '15 at 05:37

4 Answers4

4

Ok, so here is what happened.

There was a glitch in the questioner's editor, which caused the file test1.js to be blank. Hence, the code var a = true never ran.

More details: When everything was fixed up, the code worked as expected. As all of the code is already in the global scope (eg: not inside a function() {}) var a = true declared a global variable called a with the initial value of true.

So long as the code in test1.js was run before test2.js the code worked fine. Keep in mind that this means that the order the code is run in is what makes the difference. In this case, it would only depend on the order the files are listed in the test.html file. That's because even though a browser might asynchronously finish loading test2.js before test1.js has finished, it knows the order the files were specified in and reads the code in that order.

And don't forget kids: global variables are generally bad, if you really feel the need to use them, refactor your code until you change your mind :).

Maverick
  • 4,449
  • 4
  • 36
  • 46
0

Removing the var generally makes variables global. "Global" in the case of browser-based JavaScript, however, just means "window", so setting window.myVar = "something" has the same effect as myVar = "something" without the var on it.

Adrian
  • 42,911
  • 6
  • 107
  • 99
  • It's also worth noting that you need to be sure that the code in `test1.js` will run before the code in `test2.js`. – Maverick Apr 16 '15 at 23:48
  • True, though that's as it is in the example source given by OP. – Adrian Apr 16 '15 at 23:49
  • 1
    Now that the question has been edited, yes :). However, I assume abalter's actual use will be in a more complex scenario than this, so it's worth mentioning. – Maverick Apr 16 '15 at 23:50
  • I guess I assumed it was obvious you have to set before you read. Besides, that's only true if the code in test1.js/test2.js is outside of any function - if the globals are set/read inside functions (which would be the main value of them being global), then the order of the files is irrelevant, only the order of execution. – Adrian Apr 16 '15 at 23:54
  • Removing `var` is a horrible recommendation. Its a generally bad practice because it leads to accidental globals and it is incompatible with `strict` mode which is a very good practice. – jfriend00 Apr 16 '15 at 23:58
  • Removing `var` from an intentional global does not lead to accidental globals. It's true that it's bad practice, but so are globals in general... My aim was to answer the question, how to put a variable in global scope, and I gave two ways of doing so. – Adrian Apr 17 '15 at 00:03
  • @Adrian obviously only the order of execution matters, that's why I said the code in `test1.js` needs to **run** before the code in `test2.js` :) – Maverick Apr 17 '15 at 00:11
  • @Adrian - getting in the practice of doing that is just not a smart thing to do. If you want to declare something as global from a non-global location, then do the `window.x = xxx` trick rather than leave off `var` and the code will be completely obvious what it intends. Leaving off `var` is just a bad practice and prevents you from using strict mode. It should never be recommended. – jfriend00 Apr 17 '15 at 02:33
0

In Javascript, variables declared outside of a function are Global. In HTML the scope of the Javascript variable is window, if it is global. The var keyword doesn't change whether the variable is a global or not.

When you define a variable inside of a function, that variable is local to the function unless you're assigning it to the window object of the DOM or assigning the value to an already declared global variable.

In the following code we assign a Global variable a and set it to the boolean value true.

We output an alert to show it is true.

Then we fire a function that alters the variable's value to be false.

<!DOCTYPE html>
<html>
    <head>
        <title>Javascript Variable Scope</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript">
            var a = true;

        </script>    
    </head>
    <body>
        <div>TODO write content</div>
        <script type="text/javascript">
            alert('a is '+ a);

            function alterOutput(){
                a = false;
                alert('a is '+ a);
            }

            alterOutput();

            alert('a is '+ a);

        </script>



    </body>
</html>

The reason not to use global variables is because even though the variable is reassigned inside the scope of a function, because it was defined initially as a global variable, the value has been changed.

There is a write-up about Javascript variable scopes on w3schools.

When you're loading separate Javascript files the browser loads these files non-sequentially if not asynchronously. You would need to check that the first script has loaded prior to firing your dependent code.

You might even want to consider requiring the other file.

What is the simplest way to make the variable a available in test2.js?

The simplest way to make a available is to define it in the HTML header's script tag. You could also define it in test2.js for simplicity as well.

Community
  • 1
  • 1
AbsoluteƵERØ
  • 7,816
  • 2
  • 24
  • 35
-1

What is the simplest way to make the variable a available in test2.js?

Here is the simplest way I actually use.

In the HTML:

<div id="something" data-var="blank">

test1.js

 document.getElementById('something').dataset.var = 'true';

test2.js

var a = document.getElementById('something').dataset.var;
alert("a is " + a);
console.log("a is " + a);

Your variable is "glued" to the page, so it is available to every js you can load. Think to an <input type="hidden">, but more hidden.

Maybe it is not the most elegant solution, but surely it's easy, specially if you have a hundred divs in a page and don't want to deal with bulky Object to store all the values.

My hundreds of data- are created by an Ajax call, getting a template from a php include file and filling the blanks: I use them to restore fields edited by the users to their original value.

Marco Bernardini
  • 695
  • 6
  • 17
  • I actually *really* don't like this solution. Storing variables in your DOM instantly means your code is very dependent on what is being displayed on the screen. That makes me pretty uncomfortable as a developer, although it's difficult for me to articulate why I feel this is "wrong". – Maverick Apr 17 '15 at 00:21
  • I have a tree structure with more than 500 branches, and growing. Each "leaf" needs 8 values. When the tree is totally expanded, to deal with that object (as associative array) would be a bit cumbersome. Moreover my application is running on old single-core computers with a very limited RAM, so I have to try to keep the usage footprint low. – Marco Bernardini Apr 17 '15 at 00:30