Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this anchor say "search is not a function"?

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?

like image 478
赣西狠人 Avatar asked May 10 '17 02:05

赣西狠人


2 Answers

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>
like image 186
Andrew Li Avatar answered Nov 19 '22 15:11

Andrew Li


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>
like image 2
CertainPerformance Avatar answered Nov 19 '22 14:11

CertainPerformance