0

Take the following code:

HTML

<button id="button>click me</button>

JS - VERSION 1

window.onload = init;

function init() {
    console.log('init called');
    var button = document.getElementById('button');
    button.onclick = buttonClickHandler;
}

function buttonClickHandler() {
    console.log('button clicked');
}

vs Same HTML

JS - VERSION 2

window.onload = init();

In both cases, 'init called' appears in the console "immediately", but in the second case, it is followed by an error stating button is null.

There are 2 things at play here. 1) In version 1, it waits for the DOM to load 2) in version 2, it's happening before the DOM is loaded, or so it seems.

My question. Please explain as clearly as possible what is happening in version 1 vs what is happening in version 2. What are the technical terms for what window.onload = init is vs what window.onload = init() is? Also please explain each versions behaviour. Why does 1 wait, but 2 doesn't?

The script needs to go before the button element e.g. in the head: http://jsfiddle.net/XMEjr/1/

dewd
  • 4,380
  • 3
  • 29
  • 43

2 Answers2

9

Version 1 sets init function to be the one that's called on window.onload event. The function is not invoked on that line; it's just assigned (as a value) to a property.

Version 2 sets the result of init function to be the one that's called on window.onload event. It's the difference that () makes.

Apparently init function is called before onload is fired (to get that result and set it as onload handler). So the function starts, fails to find element by button id (as DOM is not ready yet), so getElementById returns null. Then trying to access onclick property of null stops it with an error.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 1
    thx. It's funny how I can write backbone and angular code, but not even know this. some might say scary, but i get on, and always write clear reusable code. I think this basic understanding is going to help a lot of things fall into place across a number of situations though. – dewd Jun 01 '13 at 11:31
  • also, i just read somewhere that when using window.onload = init() would work if init() returned a function e.g. runInit(). Then runInit() would run after the DOM has loaded. I really need to google better before asking, but you've been a great help. Thx. – dewd Jun 01 '13 at 11:35
  • You're welcome. ) Yes, you can run a specific function that returns a function; it's a value, after all. – raina77ow Jun 01 '13 at 11:37
0

in the second one you are assigning to onload the result of the call to init :)

It would be equivalent if you do:

window.onload="init()"

In this case you are assigning a String that gets evaluated upon DOM is ready.

If you do

window.onload=init

You are assigning a reference to a function. Then again, when DOM is ready, the function gets called

But if you do:

 window.onload=init()

you could do

function init() { alert ("this is called before onload, dom is not ready, button doesnt exist"); return init2; }

function init2() { alert ("this is called on load, dom is ready, button and everything in the body is now created"); }

hope you get the point.

By the way, this case would be useful to do something like this:

window.onload=init()

function init() {
    if (IS_IPHONE) return init_iphone;
    if (IS_ANDROID) return init_android;
    if (IS_WINDOWS) return init_not_supported;
}

so you select which init method to execute onload.

rupps
  • 9,712
  • 4
  • 55
  • 95