5

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?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
赣西狠人
  • 337
  • 6
  • 15
  • _"What puzzles me is that "search" is actually defined somewhere else as an empty string"_ Changing either function name or variable referencing empty string to a different identifier should resolve issue, yes? – guest271314 May 10 '17 at 02:47
  • inline function overtakes. So `onclick` was referring to the _somewhere_ empty string `search` resulting in console output. the `search` var must have been defined after the `function search()`, therefore calling it like method results in error. – Searching May 10 '17 at 02:50
  • *"What puzzles me is that "search" is actually defined somewhere else as an empty string"* - Are you saying that you have other code somewhere that explicitly defines `search` as an empty string, or that the program is behaving as if it is defined somewhere else even though it isn't in your code and you're puzzled about where that other definition might be? – nnnnnn May 10 '17 at 02:55
  • @nnnnnn Thanks for answering. Of course the latter case. I do not explicitly define such a variable. – 赣西狠人 May 10 '17 at 03:08
  • @Shiying Can you create a stacksnippets or plnkr https://plnkr.co to reproduce issue? See https://stackoverflow.com/help/mcve – guest271314 May 10 '17 at 03:10
  • @Searching Yes, and I want to know where and when is is defined. I think Andrew has already given the right answer. – 赣西狠人 May 10 '17 at 03:15
  • 1
    @guest271314 Thanks for your advice. Is this [link](https://jsbin.com/yapililise/edit?html,console,output) OK? – 赣西狠人 May 10 '17 at 03:27
  • https://jsbin.com/lizawemayi/1/edit?html,console,output – guest271314 May 10 '17 at 03:31
  • 1
    @guest271314 Thanks for your answer, but I actually knew this can be solved by changing the function name. My question was why `search` would reference something else in this code. – 赣西狠人 May 10 '17 at 03:39
  • Semantically speaking this looks like a search button so you should use a ` – cloned May 22 '19 at 08:13

3 Answers3

4

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>
Andrew Li
  • 55,805
  • 14
  • 125
  • 143
2

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>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

Change the name of the function. Just tried your code and it worked once I changed the name of the function.

<body>
<script type="text/javascript">    
    function test() {
        console.log('Searching');
    }
</script>
<a href="#" onclick="test()">Click here</a>  

A. Zaima
  • 144
  • 5