<a>
elements have a download
attribute in HTML5 as explained here, with a default value of ""
(an empty string).
This means that download === this.download
in the onclick
handler (this
is the element in onevent
attributes), and therefore the download
attribute of the element is superior to the download
property of window
.
This fiddle lists all string attributes that are present by default. You can see download
is an attribute just like innerHTML
, which also fails with the exact same reason when used as a function (i.e. trying to refer to window.innerHTML
, but instead executing elem.innerHTML()
).
As said in the comments, using window
makes for no confusion as to what property/attribute variables will evaluate to.
This scope behaviour does actually not seem to due to the this
value but rather a specific "scope chain" that is being constructed.
As per the HTML5 specification:
Lexical Environment Scope
Let Scope
be the result of NewObjectEnvironment(the element's Document, the global environment)
.
If the element has a form owner, let Scope
be the result of NewObjectEnvironment(the element's form owner, Scope)
.
Let Scope
be the result of NewObjectEnvironment(the element's object, Scope)
.
I.e. what is happening is the scope chain is window
-> document
-> element
(increasing superiority). This means that download
evaluates to element.download
and not window.download
. What also can be concluded from this is that getElementById
will bubble up to document.getElementById
(given elem.getElementById
does not exist).
I set up a systematic example so that you can see how variables bubble up the scope chain:
window.a = 1;
document.a = 2;
elem.a = 3;
window.b = 4;
document.b = 5;
window.c = 6;
Then, <a ... onclick="console.log(a, b, c)">
logs 3
, 5
, 6
when clicked.