Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "TypeError: f is not a function"?

Here is example:

var f = function(x) {
   alert(x)
}

(function() {
   f(1)
}())

Why

TypeError: f is not a function"?

like image 688
Jim Button Avatar asked Nov 30 '22 23:11

Jim Button


2 Answers

In your example, f is not a function. If you change the example, it is:

var f = function(x) {
   alert(x)
};

(function() {
   f(1)
}());

You've run afoul of automatic semicolon insertion (or a lack thereof).

Because of the ASI rules, if a line does not end with a semicolon, the parser can combine lines. In your case, the lack of a semicolon after the var f = function statement causes the parser to declare and immediately call the function, before f has been initialized, and try to assign the result to f:

var f = function(x) {
   alert(x)
}(function() {
   f(1)
}())

By simply inserting the semicolon, you force the parser to break the two statements, and the code behaves as you would expect.

The parser prefers to combine them because it sees a function and what appear to be parameters (thanks to the leading parentheses, whitespace ignored). It calls the just-declared function, which then calls f, but f has not been initialized yet and thus is not a function.

I ran into a particularly fun case of this in an old web app (before webpack and browserify existed to combine files): we were simply catting our JS files together in order and most were in IIFE modules. One script did not end with a semicolon after its module, so the next module was being passed as a parameter when initializing the first. It was a pain to find, since it happened early in the app and was a single missing semi.

In that case, we were able to fix the problem without changing any external code by adding comments between the files we were concatenating, but good practice is to end your code with a semicolon and newline. It avoids all kind of rare whitespace bugs like this.

like image 62
ssube Avatar answered Dec 05 '22 04:12

ssube


This is the case where automatic semicolon insertion lets you down and the code is interpreted as the IIFE:

var f = function(x) {
   alert(x)
}(function() {
   f(1)
}())

So that is why f is indeed not defined.

So the rule of thumb: never start the line with ( or [. Then you can safely omit semicolons.

like image 44
dfsq Avatar answered Dec 05 '22 05:12

dfsq