I wrote a function named search
that I expected to be called when the link was clicked, as the code snippet below shows:
<script>
function search() {
console.log('Searching');
}
</script>
<a href="#" onclick="search();">Click here</a>
However, the code does not work as I expected, which causes this error (in Chrome) when the link is clicked:
Uncaught TypeError: search is not a function
I tried logging search
to see why the error was thrown:
<a href="#" onclick="console.log(search)">Click here</a>
<script>
function search() {
console.log('Searching');
}
</script>
<a href="#" onclick="console.log(search);">Click here</a>
This time, the console logged an empty string each time the link is clicked. What puzzles me is that search
is actually defined somewhere else as an empty string, making my function definition useless.
So I want to know what happens when a click event is triggered, and when is search
here defined?
It turns out search
actually is referring to to the a
element's search
property which is a property that controls search parameters, which happens to be an empty string in this case. This is because with an HTMLAnchorElement
, it is special as it is used to create hyperlinks and navigate to other addresses, and thus the search
property is used to control parameters of searches by hyperlinks (similar to that of the Location
) object. Setting the search
property of an anchor element will then in turn set the global Location
instance's window.location.search
. This creates a naming conflict and because an empty string is not a function the error is thrown.
Use a different name for the function to remove this conflict. Note that if you don't use an a
, you'll see it work just fine:
<script>
function search() {
alert("foo");
}
</script>
<div onclick="search();">Click me!</div>
Li357's answer explains most of what's going on, but to add a point, the reason that
<a onclick="search();">Click me!</div>
results in search
referring to the anchor's search
property is that inline handlers have an implicit with(this)
surrounding them. To the interpreter, the above looks a bit like:
<a onclick="
with(this) {
search();
}
">Click me!</div>
And search
is a property of HTMLAnchorElement.prototype
, so that property gets found first, before the interpreter gets to looking on window
for the property name.
It's quite unintuitive. Best to avoid inline handlers, and to avoid using with
as well. You could add the event listener properly using Javascript to solve the problem too:
function search() {
console.log('Searching');
}
document.querySelector('a').addEventListener('click', search);
<a href="#">Click here</a>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With