javascripthtmlscopedom-eventsglobal-scope

How can HTML inline handlers access the global window object and variables inside it?


I was testing a piece of code. I had a function named write, and I used a button with the inline onclick handler to run write().

function write(text) {
  alert(text)
}
<button onclick='write("Some text")'>
  Write
</button>

To my surprise, write() actually executed document.write(). To be sure, I tested it with a few more functions.

function write(text) {
  alert(text)
}
<button onclick='console.log(body)'>
  document.body
</button>

Then, I wondered if they could access window. It turned out that they can. But, document.window is undefined.

console.log(document.window)

/*

Note that this example may not work due to StackSnippets using iframes

*/
<button onclick='window.open()'>
  Open blank page
</button>

function doSomething(text) {
  console.log(text)
}
<button onclick='doSomething("Some text")'>
  doSomething
</button>

So, my question is, why can inline event handlers access properties of window, even though document is the global scope, and document.window is undefined?


Solution

  • In inline event handlers, if this.property exists, it defaults to that. If not, it falls back to document.property. If even that doesn't exist, finally, it executes that code in the global window scope.

    Some examples


    In this example, the inline handler defaults to document as the global scope.

    document.someProperty = 'something'
    
    var someProperty = 'something else'
    <button onclick='console.log(someProperty)'>
      Button
    </button>

    In this example, it defaults to window.

    var someProperty = 'something'
    <button onclick='console.log(someProperty)'>
      Button
    </button>

    In yet another example, it defaults to this, which is the element.

    <button style='color: red' onclick='console.log(style.color)'>
      Button
    </button>