343

How do you tell if a function in JavaScript is defined?

I want to do something like this

function something_cool(text, callback) {
    alert(text);
    if( callback != null ) callback();
}

But it gets me a

callback is not a function

error when callback is not defined.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aaron Lee
  • 5,287
  • 5
  • 24
  • 19

23 Answers23

547
typeof callback === "function"
Daniel Liuzzi
  • 16,807
  • 8
  • 52
  • 57
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
  • 52
    This isn't really a magic string, since the set of typeof values is precisely defined in the ECMA spec. Although the syntax for this is a little goofy to begin with, it's perfectly reasonable idiomatic Javascript. – Ben Zotto Mar 30 '10 at 01:04
  • 2
    @quixoto - understood, I guess what I mean is that you still need to have a string regardless - I would rather not have any more literal strings littering my code than absolutely needed; therefore, this isn't my ideal for testing if something is a function. – Jason Bunting Sep 13 '10 at 21:10
  • 4
    And yes, "magic" was a sloppy, poor word choice - I meant "literal string" not "magic string." My bad. :) – Jason Bunting Nov 24 '10 at 22:35
  • 1
    JSPerf - http://jsperf.com/comparing-underscore-js-isfunction-with-typeof-function/8 – Chris GW Green Sep 15 '14 at 12:50
  • 2
    Make sure to remove the parenthesis on your function and only use the function name in the if-condition or the function will be invoked instead of giving you true or false. – Russell Strauss Mar 28 '17 at 20:36
251

All of the current answers use a literal string, which I prefer to not have in my code if possible - this does not (and provides valuable semantic meaning, to boot):

function isFunction(possibleFunction) {
  return typeof(possibleFunction) === typeof(Function);
}

Personally, I try to reduce the number of strings hanging around in my code...


Also, while I am aware that typeof is an operator and not a function, there is little harm in using syntax that makes it appear as the latter.

Jason Bunting
  • 58,249
  • 14
  • 102
  • 93
  • 8
    How am I supposed to use this function? I've tried `isFunction(not_defined))` where `not_defined` is name of function that is not defined and FireBug returned `not_defined is not defined` which is correct but your function should return false and not generate error... – Wookie88 Oct 22 '12 at 22:53
  • @Wookie88: Technically speaking, the function illustrated in my answer doesn't return an error so much as an error occurs because the JavaScript interpreter is trying to resolve the symbol `not_defined` in order to pass its value to `isFunction()` and fails to resolve it. Nothing can be done to the definition of `isFunction()` to solve this problem. – Jason Bunting Oct 31 '12 at 22:20
  • Tell me how to reproduce it, @bicycle... Works for me, I just tested this. If there really is a condition for which you expect it to work, and it doesn't, tell us so we know. The onus is on you... – Jason Bunting Feb 08 '13 at 01:27
  • @JasonBunting I put together a jsfiddle to illustrate it, would love to find a way to make this work, I just can't figure it out: http://jsfiddle.net/zacharyyates/rMVCe/ (Chrome 29) – Zachary Yates Sep 10 '13 at 16:26
  • 3
    @ZacharyYates The way to work around the ReferenceError would mean to avoid working with a reference to the maybe-not-defined-function. You could do the typecheck inside the function call and pass the result to the function. http://jsfiddle.net/qNaxJ/ Maybe not so nice, but at least, no strings used ;) – netiul Mar 13 '14 at 09:11
  • 9
    Or avoid a function `isFunction` and do just `(typeof no_function == typeof Function)`. – netiul Mar 13 '14 at 09:16
  • I had problems checking type, it was returning string and not function as expected. I changed from `typeof var_with_func_name` to `typeof window[var_with_func_name]`, and it worked properly. – Gardner Sep 03 '14 at 13:26
  • 5
    @JasonBunting If you're going to be that picky, you really should be using `typeof(Function())` because Function is a function; but so are Array, Object, and other built-in prototypes (for lack of a better term). If you were checking for an array you wouldn't use `typeof(array) === typeof(Array)` for example; you'd use `typeof(array) === typeof(Array())` because you actually need to evaluate the function if you're being careful and consistent. – seanmhanson Oct 26 '15 at 20:27
  • @seanmhanson - meh. I stand by my answer as-written. Your suggestion, while appearing to have the air of value, lacks it in my personal opinion. ;) But, to each his own! Consistency is overrated - true story. – Jason Bunting Nov 10 '15 at 19:51
  • I agree with @seanmhanson, by using `typeof(Function)` you implicitly let the reader assume there is also `typeof(Number)`, `typeof(Array)`, `typeof(String)`, etc. However all of of these return the string `"function"`. – 3limin4t0r Nov 03 '20 at 13:57
20
if (callback && typeof(callback) == "function")

Note that callback (by itself) evaluates to false if it is undefined, null, 0, or false. Comparing to null is overly specific.

Anish Gupta
  • 2,218
  • 2
  • 23
  • 37
Robin like the bird
  • 744
  • 1
  • 5
  • 12
  • 2
    Also note that if `callback` itself evaluates to a "false-y" value, then its typeof can *never* be "function". – Joe Jul 22 '12 at 23:11
  • 5
    @Joe, but due to short-circuiting, that test will not be performed if callback evaluates to false. – Fabio A. Aug 01 '12 at 10:12
  • 4
    this solution isn't working, because the first condition will fire an exception immediately. this may work, for a property of an object: if (obj.callback){...} – Roey Feb 05 '15 at 10:50
10

Those methods to tell if a function is implemented also fail if variable is not defined so we are using something more powerful that supports receiving an string:

function isFunctionDefined(functionName) {
    if(eval("typeof(" + functionName + ") == typeof(Function)")) {
        return true;
    }
}

if (isFunctionDefined('myFunction')) {
    myFunction(foo);
}
patriciorocca
  • 137
  • 1
  • 3
  • I think is a good answer, you are right, all the methods above fails is the function is not defined. – Matteo Conta Apr 17 '13 at 07:10
  • 1
    It's trivial to avoid undefined references - simply refer to `typeof window.doesthisexist` instead of `doesthisexist`. However, using eval (which: is evil) as shown will only work with named functions - this wouldn't work with the use case in the question. – AD7six Nov 06 '13 at 16:05
  • Be aware that this works only with global scope, while the accepted answer is working with local scope functions as well. – inf3rno Oct 14 '17 at 10:04
8

I might do

try{
    callback();
}catch(e){};

I know there's an accepted answer, but no one suggested this. I'm not really sure if this fits the description of idiomatic, but it works for all cases.

In newer JavaScript engines a finally can be used instead.

Quentin Engles
  • 2,744
  • 1
  • 20
  • 33
  • This is a neat shortcut! Though it won't work for solely testing if a function exists or is defined (without also executing it). – Beejor Jun 02 '15 at 00:42
  • That's true. I assumed a situation where the callback is optional at that execution point. I usually use `typeof callback` anyway. – Quentin Engles Aug 29 '15 at 23:53
  • That makes sense; I was focusing on the question title more than its content. Sometimes I like the simplicity of using try-catch over tons of tests for something. Do you think there's a technical disadvantage to using it, in this case versus something like typeof? Or is it mainly a matter of doing things in a more proper/expected way? – Beejor Sep 12 '15 at 04:51
  • 1
    If you want to test for multiple types then exceptions are not so good. For instance the project I'm working on right now uses a lot of type checking on one variable to see if it's a function, string, or whatever. In this project I really need the types. For this I use an array of types, and check `accepted_types.indexOf(typeof value) !== -1` to see if it's in a range of types. In this situation exceptions would be prohibitive in my opinion. – Quentin Engles Sep 15 '15 at 22:16
  • no thanks. Exceptions should be exceptional – Jonesopolis Jun 23 '22 at 14:10
8

Using optional chaining with function calls you could do the following:

function something_cool(text, callback) {
    alert(text);
    callback?.();
}

If callback is a function, it will be executed.

If callback is null or undefined, no error is thrown and nothing happens.

However, if callback is something else e.g. a string or number, a TypeError will still be thrown.

Darren G
  • 780
  • 8
  • 16
8

Try:

if (typeof(callback) == 'function')
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bdukes
  • 152,002
  • 23
  • 148
  • 175
6

New to JavaScript I am not sure if the behaviour has changed but the solution given by Jason Bunting (6 years ago) won't work if possibleFunction is not defined.

function isFunction(possibleFunction) {
  return (typeof(possibleFunction) == typeof(Function));
}

This will throw a ReferenceError: possibleFunction is not defined error as the engine tries to resolve the symbol possibleFunction (as mentioned in the comments to Jason's answer)

To avoid this behaviour you can only pass the name of the function you want to check if it exists. So

var possibleFunction = possibleFunction || {};
if (!isFunction(possibleFunction)) return false;

This sets a variable to be either the function you want to check or the empty object if it is not defined and so avoids the issues mentioned above.

Russell Ormes
  • 525
  • 8
  • 22
  • To be completely clear: my code doesn't throw the error, that's just the JavaScript parser doing that. The same would happen if you tried to use any undefined identifier in such a way. – Jason Bunting Nov 10 '15 at 19:56
5
typeof(callback) == "function"
dashtinejad
  • 6,193
  • 4
  • 28
  • 44
4
function something_cool(text, callback){
    alert(text);
    if(typeof(callback)=='function'){ 
        callback(); 
    };
}
ConroyP
  • 40,958
  • 16
  • 80
  • 86
4
if ('function' === typeof callback) ...
Andrew Hedges
  • 21,688
  • 16
  • 67
  • 79
  • 4
    A _bit_ pedantic, and still uses a string literal. How about `if(typeof Function === typeof callback)...`? :) – Jason Bunting Nov 24 '10 at 22:33
  • @JasonBunting Curious, Whats wrong with using string literal? – Abdul Rehman Apr 18 '17 at 06:56
  • @Bsienn - as I said, it's pedantic of me, but here's the thing. Let's say you use the code with the string literal, and the call to `typeof` returns something different later (maybe "Function" instead of "function"), because of a new/different implementation of JavaScript - it _feels_ like it would be less likely that a new/different implementation would break the `typeof Function === typeof callback` check because it should be the same at a semantic level. – Jason Bunting May 24 '17 at 20:40
3

Try:

if (!(typeof(callback)=='undefined')) {...}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brian
  • 3,457
  • 4
  • 31
  • 41
2

Try this:

callback instanceof Function
Conner
  • 30,144
  • 8
  • 52
  • 73
eflorico
  • 3,589
  • 2
  • 30
  • 41
  • 1
    Doesn't work. It will still give you the error. You should try it yourself before you post it as an answer. – vbullinger Sep 06 '12 at 19:09
  • @vbullinger I just tested again in Chrome, Firefox and Safari — works everywhere. With which engine did you experience trouble? – eflorico Sep 06 '12 at 21:04
  • Firefox. Did you test the case when callback wasn't defined? – vbullinger Sep 06 '12 at 21:07
  • That's because you're directly referencing an undefined variable, that never works: http://pastebin.com/UQz2AmzH – eflorico Sep 06 '12 at 21:47
  • 3
    It does work when used on a function parameter, which is what the author asked for — I suppose ECMAScript distinguishes the cases of a non-existent variable and an existing variable with a value of undefined. It would be interesting to know more about this. – eflorico Sep 07 '12 at 17:09
  • This seems to explain it pretty well: http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/ – eflorico Sep 07 '12 at 17:20
2

If you use http://underscorejs.org, you have: http://underscorejs.org/#isFunction

_.isFunction(callback);
Sudheer Aedama
  • 2,116
  • 2
  • 21
  • 39
2

If you look at the source of the library @Venkat Sudheer Reddy Aedama mentioned, underscorejs, you can see this:

_.isFunction = function(obj) {
  return typeof obj == 'function' || false;
};

This is just my HINT, HINT answer :>

VentyCZ
  • 61
  • 3
  • 7
1

I was looking for how to check if a jQuery function was defined and I didn't find it easily.

Perhaps might need it ;)

if(typeof jQuery.fn.datepicker !== "undefined")
miguelmpn
  • 1,859
  • 1
  • 19
  • 25
1

If the callback() you are calling not just for one time in a function, you could initialize the argument for reuse:

callback = (typeof callback === "function") ? callback : function(){};

For example:

function something_cool(text, callback) {
    // Initialize arguments
    callback = (typeof callback === "function") ? callback : function(){};

    alert(text);

    if (text==='waitAnotherAJAX') {
        anotherAJAX(callback);
    } else {
        callback();
    }
}

The limitation is that it will always execute the callback argument although it's undefined.

Nick Tsai
  • 3,799
  • 33
  • 36
1

Most if not all previous answers have side effects to invoke the function

here best practice

you have function

function myFunction() {
        var x=1;
    }
direct way to test for it

//direct way
        if( (typeof window.myFunction)=='function')
            alert('myFunction is function')
        else
            alert('myFunction is not defined');
using a string so you can have only one place to define function name

//byString
        var strFunctionName='myFunction'
        if( (typeof window[strFunctionName])=='function')
            alert(s+' is function');
        else
            alert(s+' is not defined');
TexWiller
  • 318
  • 2
  • 9
  • not sure why you have 'window' here . There could be scope differences : just do typeof(myFunction) === 'function' – yeahdixon Nov 03 '21 at 18:50
0

For global functions you can use this one instead of eval suggested in one of the answers.

var global = (function (){
    return this;
})();

if (typeof(global.f) != "function")
    global.f = function f1_shim (){
        // commonly used by polyfill libs
    };

You can use global.f instanceof Function as well, but afaik. the value of the Function will be different in different frames, so it will work only with a single frame application properly. That's why we usually use typeof instead. Note that in some environments there can be anomalies with typeof f too, e.g. by MSIE 6-8 some of the functions for example alert had "object" type.

By local functions you can use the one in the accepted answer. You can test whether the function is local or global too.

if (typeof(f) == "function")
    if (global.f === f)
        console.log("f is a global function");
    else
        console.log("f is a local function");

To answer the question, the example code is working for me without error in latest browers, so I am not sure what was the problem with it:

function something_cool(text, callback) {
    alert(text);
    if( callback != null ) callback();
}

Note: I would use callback !== undefined instead of callback != null, but they do almost the same.

inf3rno
  • 24,976
  • 11
  • 115
  • 197
0

If you wish to redefine functions, it is best to use function variables, which are defined in their order of occurrence, since functions are defined globally, no matter where they occur.

Example of creating a new function that calls a previous function of the same name:

A=function() {...} // first definition
...
if (typeof A==='function')
   oldA=A;
A=function() {...oldA()...} // new definition
David Spector
  • 1,520
  • 15
  • 21
0

This worked for me

if( cb && typeof( eval( cb ) ) === "function" ){
    eval( cb + "()" );
}
-1

I would rather suggest following function:

function isFunction(name) {
    return eval(`typeof ${name} === typeof Function`);
}
  • The question asked for a way to determine if a variable is a function, not a string that is the name of a function. – frogcoder Aug 18 '21 at 11:01
-2

One-line solution:

function something_cool(text, callback){
    callback && callback();
}
Samir Alajmovic
  • 3,247
  • 3
  • 26
  • 28
  • His example shows just that, that he wants the function to be called if it's defined, and if it's not, nothing happens. https://jsfiddle.net/nh1cxxg6/ Functions which return falsey / false values still get called. Of course, this doesn't work for when you want values to be returned. – Samir Alajmovic Jan 18 '16 at 20:41
  • Ah, I misread his question. However, this would cause an exception if callback is not a function. – Frank Bryce Jan 18 '16 at 20:43