227

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
  • 8,605
  • 16
  • 65
  • 130
  • 1
    Does this answer your question? [TypeError: console.log(...) is not a function](https://stackoverflow.com/questions/31013221/typeerror-console-log-is-not-a-function) – Sebastian Simon Jun 15 '21 at 12:00

11 Answers11

432

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
  • 233,099
  • 56
  • 391
  • 304
  • 1
    thanks for your explanation Josh, and @mrlew, your answer is helpful too, no need to delete that :-) – armnotstrong Feb 04 '17 at 04:24
  • 5
    @armnotstrong Josh was faster, and the answer is the same :) – mrlew Feb 04 '17 at 04:28
  • 3
    Thank you sir! My linter removed the semicolon automagically and everything broke :) – Jonas Lomholdt Sep 26 '17 at 12:44
  • 4
    awesome!!! Thank you so much!! I almost lost all my hair on this one... – Tomas Jun 09 '18 at 18:44
  • 1
    Err.... totally forgot about that. It was 2nd nature back in the jQuery days! – Matthew Pitts Dec 26 '19 at 22:44
  • 3
    this is insane and I'm so grateful for this post. I was setting state after an `if` statement in a React `useEffect()` function when I kept receiving this "... is not a function" error. – Rahul Nath May 29 '20 at 21:25
  • This type of error you can have, if you have condition for rendering and have missed logical operator like "&&" or "||". {condition && condition && condition __here is missing &&-||__ } – Руслан Nov 24 '22 at 10:00
29

To make semicolon rules simple

Every line that begins with a (, [, `, or any arithmetic operator, must begin with a semicolon if you want it to be interpreted as its own line ~ Otherwise, it may combine with the previous line by accident. All other line breaks have implicit semicolons.

That's it. Done.

  • Note that /, +, - are the only valid operators you would want to do this for anyway. You would never want a line to begin with '*', since it's a binary operator that could never make sense at the beginning of a line.

  • You should put the semicolons at the start of the line when doing this. You should not try to "fix" the issue by adding a semicolon to the previous line, or any reordering or moving of the code will cause the issue to potentially manifest again. Many of the other answers (including top answers) make this suggestion, but it's not a good practice.


Why do those particular characters need initial semicolons?

Consider the following:

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

By following the rules given, you prevent the above code from being reinterpreted 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 do not believe that doing this can let you code like a C programmer. Since it is still the case that when you don't end a line with a semicolon, Javascript might implicitly add one on your behalf against your desires. So, keep in mind statements like

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

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

The above case will happen to return/continue/break/++/--. Any linter will catch the former case with dead-code, or the latter case with ++/-- syntax error.

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
  • 4,002
  • 4
  • 24
  • 39
11

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
  • 5,071
  • 41
  • 33
7

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,178
  • 1
  • 14
  • 26
  • 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
  • 1
    @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
7

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));
  • `Function.bind` requires this strategy also--thanks – jimmont Jan 26 '21 at 10:54
  • 1
    I believe this is because an arrow function is a property in the object, while a method is a property in the prototype. So when `super.x()` tries to reference the prototype's property `x`, it's not there (`x = () => 1;` is in the object itself). This is mentioned [here](https://www.typescriptlang.org/docs/handbook/2/classes.html#arrow-functions): _"You can’t use super.getName in a derived class, because there’s no entry in the prototype chain to fetch the base class method from"_. – Branko Dimitrijevic Feb 13 '22 at 09:11
  • Thank you! I was having this exact problem and couldn't figure it out. And thank you @Branko Dimitrijevic for the explanation. – aenw Sep 14 '22 at 09:09
  • Unfortunatelly in my case, I'd like to have two possible candidates for my method, which seems impossible. Worked fine until I extended parent class... I mean, I can have some 1 uniform class method, that calls another method, it just looks ugly and I need to hope, that it will get optimized properly. – Martin Melichar Jul 10 '23 at 20:25
5
  **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
  • 5,071
  • 41
  • 33
4

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
  • 29,059
  • 15
  • 130
  • 154
3

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
  • 4,316
  • 2
  • 16
  • 30
0

My case: (Angular, PrimeNG )

My Error: enter image description here My versions:

 "@angular/animations": "^12.2.0",
 "@angular/cdk": "^12.2.0",
 "@angular/common": "^12.2.0",
 "@angular/compiler": "^12.2.0",
 "@angular/core": "^12.2.0",
 "@angular/forms": "^12.2.0",
 "@angular/platform-browser": "^12.2.0",
 "@angular/platform-browser-dynamic": "^12.2.0",
 "@angular/router": "^12.2.0",
 "primeng": "^13.0.0-rc.2",
 "quill": "^1.3.7"

My solution: node_modules/primeng/fesm2015/primeng-editor.mjs

update the import for Quill like in the image enter image description here

Sorin Veștemean
  • 1,772
  • 19
  • 17
0

I had the same error in React and it took me ages to figure out the problem,

enter image description here

The cause was not wrapping context around my app

enter image description here

Go to your index.jsx (or main.jsx in ViteJS) and check that you have Context wrapped around your app.

Aindriú
  • 3,560
  • 9
  • 36
  • 54
0

If comming from Ionic Angular update to latest version

ng update @ionic/angular
RicardoVallejo
  • 793
  • 7
  • 11