I have a website with three files:
index.html
<html>
<head>
<script src="First.js"></script>
<script src="Second.js"></script>
</head>
<body></body>
</html>
First.js
window.onload = Main;
Second.js
function Main() { var foo = 1; }
When I open the page, I expect the variable ‘foo’ to be set to ‘1’. Instead, when I open the page, it breaks indicating ‘Main is not defined’ and ‘Main()’ is never called.
If the ‘.onload’ event for the window isn’t supposed to fire until the page is fully loaded and thus assumingly both scripts have been loaded, why doesn’t the window object have a reference to the ‘Main()’ method in ‘Second.js’? Should ‘Main()’ be a globally accessible function?
NOTE: I realize I can change the order in which I load the scripts and then my code would work, but that’s not the purpose of my question. What I really want to do is validate my assumption.
It doesn’t work because the code in
<script>elements are run sequentially and independently (this assumes synchronous scripts, the default). That is, two different<script>sections cannot forward-reference each other. Now, JavaScript “hoists”function name () {}constructs within the same context, so this would have worked “out of order” in a single<script>.Preamble / warning:
Consider not using
onload. If something else tries to use it (onload), then something will likely break. (I recommend jQuery because it “gets this right” and “is so darn easy”… then again, so do many other frameworks. Pick one 🙂For instance, this would work in jQuery:
Explanation of why it works (and how to fix it without reordering scripts or using jQuery):
Note that in this case the jQuery internal event handler is called, which calls the anonymous callback, which then calls
Main(which is now resolves to a function-object). The “similar” code here would be:These work because
Mainis not evaluated until the onload has occurred, in which case all the [synchronous]<script>elements have been executed. (Please see my comment as to what it means to evaluateMain.)On the other hand,
window.onload = Main(orjQuery(Main)) evaluateMainright-then and use the resulting value; as others have noted,Mainis not set (“is undefined”) at this point due to the ordering of the<script>elements (they run sequentially).Please refer to the note at top as to why to not to use
onloaddirectly 😉Happy coding.