173

Everything works fine when I wrote the js logic in a closure as a single js file, as:

(function(win){
   //main logic here
   win.expose1 = ....
   win.expose2 = ....
})(window)

but when I try to insert a logging alternative function before that closure in the same js file,

 window.Glog = function(msg){
     console.log(msg)
 }
 // this was added before the main closure.

 (function(win){
   //the former closure that contains the main javascript logic;
 })(window)

it complains that there is a TypeError:

Uncaught TypeError: (intermediate value)(...) is not a function

What did I do wrong?

armnotstrong
  • 7,047
  • 10
  • 51
  • 108

8 Answers8

342

The error is a result of the missing semicolon on the third line:

window.Glog = function(msg) {
  console.log(msg);
}; // <--- Add this semicolon

(function(win) {
  // ...
})(window);

The ECMAScript specification has specific rules for automatic semicolon insertion, however in this case a semicolon isn't automatically inserted because the parenthesised expression that begins on the next line can be interpreted as an argument list for a function call.

This means that without that semicolon, the anonymous window.Glog function was being invoked with a function as the msg parameter, followed by (window) which was subsequently attempting to invoke whatever was returned.

This is how the code was being interpreted:

window.Glog = function(msg) {
  console.log(msg);
}(function(win) {
  // ...
})(window);
Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
11

To make semicolon rules simple

Every line that begins with a (, [, `, or any operator (/, +, - are the only valid ones), must begin with a semicolon to be interpreted as its own line. All other line breaks are implicit.

That's it. Done.


Why?

Consider the following:

func()
;[0].concat(myarr).forEach(func)
;(myarr).forEach(func)
;`hello`.forEach(func)
;/hello/.exec(str)
;+0
;-0

Following the above rules prevent the above from being interpreted as

func()[0].concat(myarr).forEach(func)(myarr).forEach(func)`hello`.forEach(func)/hello/.forEach(func)+0-0

Additional Notes

To mention what will happen: brackets will index, parentheses will be treated as function parameters. The backtick would transform into a tagged template, regex will turn into division, and explicitly +/- signed integers will turn into plus/minus operators.

Of course, you can avoid this by just adding a semicolon to the end of every linebreak, but even doing that won't always help you, since when you don't end a line with a semicolon, it might implicitly add one on your behalf. So keep in mind statements like

return       // Implicit semicolon, will return undefined.
    (1+2);

i        // Implicit semicolon on this line
   ++;   // But, if you intended "i++;" and you wrote it like this,
         // you need help.

The above case will happen to return/continue/break/++/--. Any linter will catch this with dead-code or ++/-- syntax error (++/-- will never realistically happen).

Finally, if you want file concatenation to work, make sure each file ends with a semicolon. If you're using a bundler program (recommended), it should do this automatically.

Nicholas Pipitone
  • 3,479
  • 1
  • 19
  • 34
7

Error Case:

var userListQuery = {
    userId: {
        $in: result
    },
    "isCameraAdded": true
}

( cameraInfo.findtext != "" ) ? searchQuery : userListQuery;

Output:

TypeError: (intermediate value)(intermediate value) is not a function

Fix: You are missing a semi-colon (;) to separate the expressions

userListQuery = {
    userId: {
        $in: result
    },
    "isCameraAdded": true
}; // Without a semi colon, the error is produced

( cameraInfo.findtext != "" ) ? searchQuery : userListQuery;
Community
  • 1
  • 1
Shashwat Gupta
  • 3,139
  • 23
  • 21
4

For me it was much more simple but it took me a while to figure it out. We basically had in our .jslib

some_array.forEach(item => {
    do_stuff(item);
});

Turns out Unity (emscripten?) just doesn't like that syntax. We replaced it with a good old for-loop and it stoped complaining right away. I really hate it that it doesn't show the line it is complaining about, but anyway, fool me twice shame on me.

tfrascaroli
  • 1,041
  • 1
  • 11
  • 25
  • my guess is that your issue was something to do with [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) – brandito Aug 21 '19 at 05:49
  • This is a different case than what the question is about. – CherryDT Jul 03 '20 at 07:49
  • @CherryDT it is not, since the error I was getting was the exact same one. – tfrascaroli Jul 03 '20 at 10:00
  • No, this question is about errors you get from accidentally calling something as a function due to no semicolon existing between the statement and a `(` on the next line. I don't see any of that in your case. The question doesn't only consist of its title! – CherryDT Jul 03 '20 at 10:07
2

When I create a root class, whose methods I defined using the arrow functions. When inheriting and overwriting the original function I noticed the same issue.

class C {
  x = () => 1; 
 };
 
class CC extends C {
  x = (foo) =>  super.x() + foo;
};

let add = new CC;
console.log(add.x(4));

this is solved by defining the method of the parent class without arrow functions

class C {
  x() { 
    return 1; 
  }; 
 };
 
class CC extends C {
  x = foo =>  super.x() + foo;
};

let add = new CC;
console.log(add.x(4));
1

I have faced this issue when I created a new ES2015 class where the property name was equal to the method name.

e.g.:

class Test{
  constructor () {
    this.test = 'test'
  }

  test (test) {
    this.test = test
  }
}

let t = new Test()
t.test('new Test')

Please note this implementation was in NodeJS 6.10.

As a workaround (if you do not want to use the boring 'setTest' method name), you could use a prefix for your 'private' properties (like _test).

Open your Developer Tools in jsfiddle.

GuyT
  • 3,725
  • 2
  • 14
  • 29
0
  **Error Case:**

var handler = function(parameters) {
  console.log(parameters);
}

(function() {     //IIFE
 // some code
})();

Output: TypeError: (intermediate value)(intermediate value) is not a function *How to Fix IT -> because you are missing semi colan(;) to separate expressions;

 **Fixed**


var handler = function(parameters) {
  console.log(parameters);
}; // <--- Add this semicolon(if you miss that semi colan .. 
   //error will occurs )

(function() {     //IIFE
 // some code
})();

why this error comes?? Reason : specific rules for automatic semicolon insertion which is given ES6 stanards

Shashwat Gupta
  • 3,139
  • 23
  • 21
0

I faced same issue with this situation:

let brand, capacity, color;
let car = {
  brand: 'benz',
  capacity: 80,
  color: 'yellow',
}

({ color, capacity, brand } = car);

And with just a ; at the end of car declaration the error disappred:

let car = {
  brand: 'benz',
  capacity: 80,
  color: 'yellow',
}; // <-------------- here a semicolon is needed

Actually, before ({ color, capacity, brand } = car); it is needed to see semicolon.

AmerllicA
  • 15,720
  • 11
  • 72
  • 103