6

Given this code:

<button id="blah" onclick="alert(id)">Click me</button>

Clicking the button will alert "blah". Why does the id attribute become a variable visible within the scope of the onclick handler?

Another example:

<button style="font-size:200%" onclick="console.log(style)">Click me</button>

Here we see that style refers to a CSSStyleDeclaration object, rather than the string value of the attribute. This is similar to what we'd get by referencing an index of the button element's attributes property, or through attribute properties like this.style (getAttribute would return the string value instead).

Where is this behavior specified?

http://jsfiddle.net/b8mpJ/

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141

2 Answers2

2

Because it's specified in Web Applications API. Quoting whatWG's Living Standard:

When the user agent is to get the current value of the event handler H, it must run these steps:

[...] Using the script execution environment obtained above, create a function object with:

[...] Lexical Environment Scope

  • Let Scope be the result of NewObjectEnvironment(document, the global environment).

  • If form owner is not null, let Scope be the result of NewObjectEnvironment(>form owner, Scope).

  • If element is not null, let Scope be the result of NewObjectEnvironment(element, Scope).

NewObjectEnvironment() is defined in ECMAScript edition 5 section 10.2.2.3. You may probably know its effect better from with statement (where it's used as well). In other words, the target element's properties are checked as well when looking for a particular name binding in the event handler's function.

Community
  • 1
  • 1
raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • I think you nailed it. Might be good to quote ES5 section 10.2.2.3 here for anyone else who comes across this; steps 2 and 3 are vital to understanding why this happens. Thanks. – Dagg Nabbit Dec 24 '13 at 21:54
  • Minor nit-pick, but given that whatWG reflects what browsers actually do, saying the behaviour is *because* of whatWG is probably backwards (for now): whatWG is just documenting what browsers do in an attempt to standardise behaviour. ;-) – RobG Dec 24 '13 at 22:04
  • @RobG, do you happen to know if this behavior has "always" existed? Somehow I've never noticed it before today. – Dagg Nabbit Dec 24 '13 at 22:08
  • 1
    @DaggNabbit Haven't found any reference for 'always', but [this article](http://whattheheadsaid.com/2010/12/scoping-with-html-and-inline-event-attributes) describing the same problem is quite (2010) old. ) – raina77ow Dec 24 '13 at 22:42
  • @raina77ow, interesting article, thanks. Hearing that it took old PointedEars any amount of time to work this out makes me feel not quite so dumb for being stumped by it. ;) – Dagg Nabbit Dec 24 '13 at 22:59
  • @DaggNabbit—no idea when it came into being, but I suspect very early (a "DOM 0" thing). I've never seen anyone rely on this behaviour, it surprises me that it's been "standardised" as it seems like a bad idea, like making IDs and NAMEs global variables (which, though implemented in every browser to be compatible with ancient IE, has not been similarly "standardised" as far as I know). – RobG Dec 25 '13 at 00:31
  • 1
    @DaggNabbit—it seems to have been there from the very beginning: [stackoverflow.com/a/9160009/855543](http://stackoverflow.com/a/9160009/855543). – RobG Dec 25 '13 at 23:51
0

I'm not sure where it is specified, but what's happening is that your handler is being called with the this variable set to the element. That's why the attributes are visible, since id could be seen as a shorthand form of this.id.

toon81
  • 868
  • 1
  • 5
  • 13