I just spent a long time figuring out that I shouldn't use clear() as the name of a function in Javascript:
<head>
<script type="text/javascript" src="Array.js"></script>
</head>
<body>
Hello!!!!<br>
<button type="button" onClick="clear()" id="ppp">Shoo!</button><br>
<button type="button" onClick="add()" id="add">Add a few elements</button><br>
<button type="button" onClick="check()" id="check">Check the array</button><br>
<p id="results">Results will appear here.</p>
<script type="text/javascript">
initialize();
</script>
</body>
Here's Array.js:
var results;
function initialize(){
results = document.getElementById("results");
}
function add() {
results.firstChild.data="add";
}
function clear() {
results.firstChild.data = "Hello?";
}
function check() {
results.firstChild.data = "check";
}
Symptoms: Clicking the 'add' and 'check' buttons gives me the result I expect, but clicking the 'clear' button does nothing.
If I rename clear() to clearxyz(), it works fine.
My questions:
- Is "clear" a reserved word? I don't see it on the list: https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words
- Is there a debugging trick I should be using to figure this kind of thing out in the future? It took me a long time (I'm a noob!) to figure out that the name of the function was my problem.
Many thanks. Edit: I'm using Firefox 6.0, and I added a line break to show where Array.js starts.
Not according to the MDN.
Edit:
You got me curious, so I threw together this little jsfiddle.
Having a function named
clear
seems to work just fine.As the others said,
clear
is not a reserved keyword. It seems that the called function isdocument.clear
[MDN]. Invokinginside the event handler returns
true
.DEMO
So it seems,
document
is in the scope chain of the event handler.... the question now is why.JavaScript: The Definitive Guide says:
As your method is global, meaning it is a property of the
window
object, it is not found in the scope chain, asdocument.clear
comes earlier in the scope chain.I haven't found any specification for this. The guide also says that one should not rely on that, so I assume this is nothing official.
If you have form elements inside a form, then even the corresponding
form
element will be in the scope chain (not sure whether this holds for all browsers though). This is another reason for confusion.There are two (not exclusive) ways to avoid such situations:
Don't use inline event handlers. It is considered bad practice as it is mixing logic and presentation. There are other ways to attach event handlers.
Don't pollute the global namespace. Create one object in global scope (with a name you are sure of does not collide with any
window
ordocument
properties or ids of HTML elements) and assign the functions as properties of this object. Whenever you call a function, you reference it through this object. There also other ways to namespace your code.No,
clear
is not a reserved keyword.The problem is that, since you use an event handler content attribute, your global function
window.clear
is shadowed by the obsoletedocument.clear
.This behavior is explained in step 10 of getting the current value of the event handler:
That means that the global scope is shadowed by
Therefore, you can
Rename your function.
This approach is not completely reliable because some browser could implement a non-standard feature which shadows your variables. Or a future spec could introduce that feature (example).
Call your function as a method of the global object.
For example, assuming
window
is not shadowed, you can usewindow.clear
.Avoid event handler content attributes.
Instead, you can use event handler IDL attributes or event listeners.
Good question. I think the problem is a scoping issue - your
onClick="clear()"
is not going to theclear
function you defined, but I'm not sure where it's going. Changing it towindow.clear()
or a new function that simply calls yourclear
works.