Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"is not a function" error when another unrelated function is in the code

I have two pieces of code that each work as expected:

function Test() {}

let tmp = function() {
    console.log(this)
}
tmp.call(Test)

and

function Test() {}

(function() {
    console.log(this)
}).call(Test)

They both produce the expected output: [Function: Test].

However, when these independent code fragments are combined, it produces an error. So, running the following code

function Test() {}

let tmp = function() {
    console.log(this)
}
tmp.call(Test)

(function() {
    console.log(this)
}).call(Test)

results in

TypeError: tmp.call(...) is not a function

I found a non-elegant fix for this, which is adding a delay to the second code fragment. So, the following would produce the desired output ([Function: Test] twice):

function Test() {}

let tmp = function() {
    console.log(this)
}
tmp.call(Test)

setTimeout(() => {
    (function() {
        console.log(this)
    }).call(Test)
}, 100);

The fact that the timeout seems to fix it makes me think it's related to some asynchronous stuff, but I can't explain exactly why it's happening.

like image 924
zlotnleo Avatar asked Dec 17 '22 19:12

zlotnleo


2 Answers

You're falling victim to an automatic semicolon insertion trap. The code

tmp.call(Test)

(function() {
    console.log(this)
}).call(Test)

is interpreted as if it were written

tmp.call(Test)(function() { console.log(this) }).call(Test)

If a semicolon is introduced:

tmp.call(Test);

(function() {
    console.log(this)
}).call(Test)

then it will work.

The precise rules involve some "legalese" that's somewhat hard to digest, but the basic idea (in this case) is that a semicolon won't be inserted when an expression can syntactically work when the newline is considered to be a simple space character.

like image 90
Pointy Avatar answered Dec 28 '22 08:12

Pointy


This is how your code snippet is interpreted:

function Test() {}

let tmp = function() {
    console.log(this)
}
tmp.call(Test)(function() {
    console.log(this)
}).call(Test)

To fix it, add a semi-colon after tmp.call(Test)

like image 38
Evert Avatar answered Dec 28 '22 09:12

Evert