Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Function and Form Name conflict

Tags:

javascript

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 form name would be in conflict with a function name, but I change the name anyway and everything worked fine. Does anyone know why this would even happen?

If you run this code it will fail, but if you change the form name it works, very strange.

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function mytest(){alert("hello");}
</script>
</head>
<body>
<form name="mytest" ></form>
<a  href="#" onClick="mytest();">Click Me</a>
</body>
</html>

I am running this on IE6. What is strange to me is that one is Javascript code and the other is an attribute of HTML.

Live link where you can see this happening:
JSBin

like image 540
Tony Borf Avatar asked Sep 12 '09 18:09

Tony Borf


2 Answers

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).

like image 137
AnthonyWJones Avatar answered Sep 22 '22 17:09

AnthonyWJones


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>
like image 23
Guffa Avatar answered Sep 24 '22 17:09

Guffa