2

When using event handler content attributes in HTML, according to the specification, the value of this in the callback refers to the event's currentTarget property (the input DOM element in the example below). To access one of the DOM element's attributes, this can be done as follows:

<input type="text" onclick="console.log(this.type)"><!-- logs "text" -->

However, when writing an answer to another question, I somewhat unexpectedly found out that it's possible to refer to the element's properties using their unqualified property names. The following has been tested in current versions of both Chrome and Firefox:

<input type="text" onclick="console.log(type)"><!-- logs "text" -->
<input type="text" onclick="console.log(required)"><!-- logs "false" -->
<input type="text" onclick="console.log(tagName)"><!-- logs "INPUT" -->

Now, my question is: is this behavior specified somewhere? I don't seem to find anything in the HTML specification or the DOM UI events specification, and my Google searches are also turning up empty.

Dennis Kats
  • 2,085
  • 1
  • 7
  • 16
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156

1 Answers1

2

After more research, I seem to have found the answer in section 17.1.6 of JavaScript: The Definitive Guide.

It all comes down to the scope chain that is used to resolve identifiers. For a normal function defined in the global scope, when resolving an identifier x, the runtime will first perform a lookup in the function's local scope, and if that fails it will try to find it in the global scope.

For HTML event handler content attributes, the scope chain is different. After trying to resolve the identifier in the event handler's local scope (1), JavaScript will try to find it in the scope of the element to which the event handler is attached (2), and continue up the hierarchy (3) until it reaches the global scope (4).

<form>
    <!--1--><input id="a" type="text" onclick="var x = 'y'; console.log(x)" />
    <!--2--><input id="b" type="text" onclick="console.log(type)" />
    <!--3--><input id="c" type="text" onclick="console.log(b.id)" />
    <!--4--><input id="d" type="text" onclick="console.log(location.href)" />
</form>

According to the aforementioned book, the composition of the scope chain was never standardized, and may be implementation-dependent.

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • I believe this is now part of the HTML specification as seen in [section 8.1.8.1](https://html.spec.whatwg.org/multipage/webappapis.html#getting-the-current-value-of-the-event-handler). In particular, see how the `scope` argument is constructed. And from what I can tell, Chrome implements this behavior internally using `with` blocks. – Dennis Kats Jun 22 '23 at 17:32