100

Code is as follows:

<body>
    <a href="javascript:;" id="test">hello</a>
</body>

<script type="text/javascript">
    document.getElementById("test").addEventListener("click", function () {
      test()
    }, false)
    function test() {
      var postTypes = new Array('hello', 'there')   
      (function() { alert('hello there') })()
    }
</script>

This will throw an:

"Uncaught TypeError: object is not a function"

If I wrap the anonymous function call/invocation in another set of parentheses it will execute the alert, but still give me an error. If I put a semi-colon after the "var postTypes" definition then it will completely fine.

I was led to believe that javascript does not require semi-colons, so I'm making a guess that there is some weird associativity rules of function application that I am not fully understanding. Why am I getting this error?

Cœur
  • 32,421
  • 21
  • 173
  • 232
PolandSpring
  • 2,384
  • 6
  • 22
  • 35
  • Looks almost like you are trying to create both an anonymous function and static function and expecting it to execute as one. What happens if you remove function() – brumScouse Oct 26 '10 at 18:45

6 Answers6

91

JavaScript does require semicolons, it's just that the interpreter will insert them for you on line breaks where possible*.

Unfortunately, the code

var a = new B(args)(stuff)()

does not result in a syntax error, so no ; will be inserted. (An example which can run is

var answer = new Function("x", "return x")(function(){return 42;})();

To avoid surprises like this, train yourself to always end a statement with ;.


* This is just a rule of thumb and not always true. The insertion rule is much more complicated. This blog page about semicolon insertion has more detail.
Michael Mior
  • 26,133
  • 8
  • 80
  • 110
kennytm
  • 469,458
  • 94
  • 1,022
  • 977
  • 15
    Or: To avoid surprises like this, train yourself to write clean readable code (which should always apply) and know the general ASI rules... it really is no different than "knowing" how closures in JS work. –  Oct 26 '10 at 19:03
19

Your code experiences a case where the Automatic Semicolon Insertion (ASI) process doesn't happen.

You should never rely on ASI. You should use semicolons to properly separate statements:

var postTypes = new Array('hello', 'there'); // <--- Place a semicolon here!!

(function() { alert('hello there') })();

Your code was actually trying to invoke the array object.

p.matsinopoulos
  • 7,374
  • 6
  • 41
  • 84
Christian C. Salvadó
  • 723,813
  • 173
  • 899
  • 828
9

I got a similar error and it took me a while to realize that in my case I named the array variable payInvoices and the function also payInvoices. It confused AngularJs. Once I changed the name to processPayments() it finally worked. Just wanted to share this error and solution as it took me long time to figure this out.

Naomi
  • 708
  • 1
  • 8
  • 25
  • Same here, I had a variable named `alert` and was trying to call the javascript alert function and it would say 'alert is not a function'. It was trying to call the `alert` variable instead of the actual function – James111 Oct 05 '15 at 02:54
0

Try to have the function body before the function call in your JavaScript file.

CMPE
  • 1,485
  • 2
  • 17
  • 29
0

I was getting this same error and spent a day and a half trying to find a solution. Naomi's answer lead me to the solution I needed.

My input (type=button) had an attribute name that was identical to a function name that was being called by the onClick event. Once I changed the attribute name everything worked.

<input type="button" name="clearEmployer" onClick="clearEmployer();">

changed to:

<input type="button" name="clearEmployerBtn" onClick="clearEmployer();">
tbriggs707
  • 79
  • 7
0

I have this error when compiling and bundling TS with WebPack. It compiles export class AppRouterElement extends connect(store, LitElement){....} into let Sr = class extends (Object(wr.connect) (fn, vr)) {....} which seems wrong because of missing comma. When bundling with Rollup, no error.

Dzintars
  • 913
  • 13
  • 19