Why does this anchor say "search is not a function"?
I wrote a function with a name search
that I expected to be called when the link was clicked as shown below:
<script>
function search() {
console.log('Searching');
}
</script>
<a href="#" onclick="search();">Click here</a>
However, the code doesn't work as I expected, resulting in this error (in Chrome) when clicking on a link:
Uncaught TypeError: search is not a function
I tried to login search
to understand why the error occurred:
<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 was writing a blank line every time the link was clicked. What puzzles me is what is search
actually defined somewhere else as an empty string, which makes my function definition useless.
So I want to know what happens when the click event fires and when is it defined here search
?
source to share
It turns out search
to be referring to the a
element property search
, which is the property that controls the search parameters, which in this case is an empty string. This is because using HTMLAnchorElement
it is special in that it is used to create hyperlinks and navigate to other addresses, and thus the property is search
used to control the parameters of a hyperlink search (similar to a parameter Location
). Then setting the search
binding element property will set the global instance Location
window.location.search
. This also creates a naming conflict because the empty string is not the function that is causing the error.
Use a different name for the function to remove this conflict. Please note, if you don't use a
, you will see that it works fine:
<script>
function search() {
alert("foo");
}
</script>
<div onclick="search();">Click me!</div>
source to share
Li357's answer explains most of what's going on, but just to add a point, the reason why
<a onclick="search();">Click me!</div>
The results of search
referencing the search
binding property are that inline handlers have an implicit environment with(this)
. For the interpreter, the above looks something like this:
<a onclick="
with(this) {
search();
}
">Click me!</div>
And search
is a property HTMLAnchorElement.prototype
, so the property will be found first, before the interpreter HTMLAnchorElement.prototype
searches for window
the property name.
It's not intuitive at all. It is best to avoid built-in handlers, and also avoid using with
. You can add an event handler correctly using Javascript to solve the problem:
function search() {
console.log('Searching');
}
document.querySelector('a').addEventListener('click', search);
<a href="#">Click here</a>
source to share