117

The 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 semicolon after the "var postTypes" definition then it will be completely fine.

I was led to believe that JavaScript does not require semicolons, 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?

1
  • 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() Commented Oct 26, 2010 at 18:45

7 Answers 7

95

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
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.

4 Comments

One way to fix the issue, but I can't get behind the Crockford-club.
@pst: Let me rephrase, I'm not in the Crock's-club at all :)
In that case I apologize for the harsh words :(
I did enjoy the quiz. ASI is indeed terribly confusing with icky-code!
15

I ran into this problem in React: I tried to destructure and use a named export when it was a default export, for example:

// module.js
const myFunction = () => null
export default myFunction
// component.js
// THIS WAS WRONG:
// import { myFunction } from './module'
// SHOULD BE THIS:
import myFunction from './module'

3 Comments

Exactly my issue here too
This was also my problem in a VueJs app, which leads me to believe it's more about how to use modules with Webpack.
The key here is, that you're exporting the function as "default". So you don't hat to put it in curly brackets to deconstruct. If you had exported it like this export default myFunction this import { myFunction } from './module' would have worked
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.

1 Comment

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
0

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

Comments

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();">

Comments

0

I have this error when compiling and bundling TypeScript code 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 the missing comma. When bundling with Rollup, no error.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.