Last updated: Mar 3, 2024
Reading timeยท4 min

Use the typeof operator to check if a function is defined.
The typeof operator returns a string that indicates the type of a value. If
the function is not defined, the typeof operator returns "undefined" and
doesn't throw an error.
function greet() { return 'hello world'; } if (typeof greet === 'function') { // ๐๏ธ this runs console.log('โ function is defined'); console.log(greet()); // ๐๏ธ hello world } else { console.log('โ๏ธ function is NOT defined'); }

We used the typeof operator to check if a function is defined.
The operator returns a string that indicates the type of a value. Here are some examples:
console.log(typeof (() => {})); // ๐๏ธ "function" console.log(typeof function () {}); // ๐๏ธ "function" console.log(typeof null); // ๐๏ธ "object" console.log(typeof []); // ๐๏ธ "object" console.log(typeof {}); // ๐๏ธ "object" console.log(typeof ''); // ๐๏ธ "string" console.log(typeof 0); // ๐๏ธ "number"

The typeof operator doesn't throw an error when used with a variable that is
not declared, instead, it returns the string "undefined".
console.log(typeof doesNotExist); // ๐๏ธ "undefined"
However, if you use the typeof operator before declaring a variable with the
let or const keywords, you would get an error.
// โ๏ธ ReferenceError: Cannot access 'myFunction' before initialization if (typeof myFunction === 'function') { console.log('โ function is defined'); } else { console.log('โ๏ธ function is NOT defined'); } const myFunction = () => {};
We used the typeof operator before initializing a function using the const
keyword.
We would get the same result if we declared the function using the let
keyword.
However, if we use the var keyword, we won't get an error because of how
hoisting works in
JavaScript.
if (typeof myFunction === 'function') { console.log('โ function is defined'); } else { // ๐๏ธ This runs console.log('โ๏ธ function is NOT defined'); } var myFunction = () => {};
We declared the function using the var keyword, so we didn't get an error when
using the typeof operator, however, the else block ran.
This is what happens under the hood when using the var keyword.
var myFunction; if (typeof myFunction === 'function') { console.log('โ function is defined'); } else { // ๐๏ธ This runs console.log('โ๏ธ function is NOT defined'); } myFunction = () => {};
The declaration of the variable gets hoisted to the top, however, the assignment of the value remains where it is.
Named functions get hoisted to the top, so you can call a named function even before the line on which it is declared.
if (typeof greet === 'function') { // ๐๏ธ this runs console.log('โ function is defined'); console.log(greet()); // ๐๏ธ hello world } else { console.log('โ๏ธ function is NOT defined'); } function greet() { return 'hello world'; }
You can imagine that the declaration of the greet() function was moved to
line 1.
When the if statement runs, the function is available in the scope and can be
called.
Note that only named functions (ones that use the function keyword) get
hoisted to the top of the file.
try/catch blockThis is a three-step process:
try/catch statement.try block will run successfully.catch block will run.try { const result = greet(); console.log(result); // ๐๏ธ hello world } catch (err) { console.log('The function is not defined'); } function greet() { return 'hello world'; }

We called the function in a try/catch block.
The function is defined and available in the scope, so the try block
completed.
If the function is not defined, the catch block runs.
try { const result = greet(); console.log(result); } catch (err) { // ๐๏ธ this runs console.log('The function is not defined'); }
We tried to call a function that doesn't exist in the scope, so the error got
passed to the catch block.
The catch block handles the error, so your program won't crash due to an
unhandled error.
instanceofYou can also use the instanceof operator to check if a variable is a function.
The instanceof operator will return true if the variable is of type function
and false otherwise.
function sum(a, b) { return a + b; } if (sum instanceof Function) { // ๐๏ธ this runs console.log('โ The variable is of type function'); } else { console.log('โ๏ธ The variable is NOT of type function'); }

The syntax for the
instanceof operator
is object instanceof constructor.
The operator returns true if the prototype property of the constructor
appears anywhere in the prototype chain of the object.
instanceof operator is that it won't work as expected if you're checking a function that is from another document, e.g. an iframe.Each document will have its own Function object, so the instanceof check
should not be used in this scenario.
The typeof operator would work as expected even if the function comes from a
different document (e.g. an iframe).
You can also convert a value to a string to check if it is a function.
function isTypeFunction(f) { const functionTypes = [ '[object Function]', '[object AsyncFunction]', ]; return functionTypes.includes( Object.prototype.toString.call(f), ); } // โ synchronous function function subtract(a, b) { return a - b; } // โ asynchronous function async function sum(a, b) { return a + b; } console.log(isTypeFunction(sum)); // ๐๏ธ true console.log(isTypeFunction(subtract)); // ๐๏ธ true console.log(isTypeFunction('abc')); // ๐๏ธ false

We used the toString() method to convert the passed-in value to a string and
compared the output to the result of calling the method with a function.
// โ for sync functions function subtract(a, b) { return a - b; } // ๐๏ธ "[object Function]" console.log(Object.prototype.toString.call(subtract)); // -------------------------------------------------- // โ for async functions async function sum(a, b) { return a + b; } // ๐๏ธ "[object AsyncFunction]" console.log(Object.prototype.toString.call(sum));
Converting a synchronous function to a string returns "[object Function]", whereas converting an async function to a string returns "[object AsyncFunction]".
This code sample is for demonstration purposes only as there is no good reason to use this approach.
Using the typeof operator should be your preferred approach as it is the most
performant, readable and works between different contexts (e.g. in iframes).