I have a javascript function that would not run and threw an error. It took about an hour to realize that my form had the same name as the function. It seemed odd that a for
To add some detail to what is happening here you need to understand javascript's scope chain.
Scope Object
A scope object is a hidden object created when a function is executed on which variables declared with var
are placed as properties, also any named function
inside the executing function are also placed as properties on the scope object.
When an identifier such as mytest
is requested javascript searches for that name attached to the current scope object (btw the scope object is also known as the "execution context").
Scope Chain
When a function is declared inside a function the current scope object is attached to the function. When this inner function is executing (and therefore has its own scope object) the code executing has access to not only the current scope object but also the scope object in which the currently executing function was created. Stop Here, Re-read that last sentence. This is known as the scope chain, the chain will be as deep as there are functions inside of functions (this happens a lot when using frameworks like JQuery).
Hence when the search for an identifier fails on the current scope object it takes a look at the next scope object up the chain. It keeps walking up the chain until it hits the global object (functions declared at the global level have the global object as their scope object).
Event Attribute Weirdness
When browsers execute code inside the text of an attribute such as onclick it treats this code as if it were a function. However browsers will do odd things with the apparent scope chain attached to this "function". Typically they inject the current element and the document element (and maybe other elements in between) as if they were scope objects into the scope chain.
So for example change the onclick code in your example to "alert(href)". You will see the path to your page followed by #
in the alert box. This is because the current element is in the scope chain and hence href
is resolved by its href
property.
In the case in the question the code arrives at the document
in the scope chain (which is placed above the global window object) and finds the identifier "mytest" (which is reference to a form) and hence attempts to use the value of that as a function (and fails).
The function is a member in the window
object, and the form is a member of the forms
collection in the document
object. When the script looks for a match for the identifier "mytest", it first looks in the document
object, and if it's not found there it looks in the window
object.
You can access the function even with the conflicting form name if you specify that it's in the window
object:
<a href="#" onClick="window.mytest();">Click Me</a>