How to check if function exists in JavaScript?

Viewed 646570

My code is

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

However, sometimes my onChange does not load. Firebug errors with

me.onChange is not a function

I want to degrade gracefully because this is not the most important feature in my program. typeof gives the same error.

Any suggestions on how to make sure that it exists and then only execute onChange?

(None of the methods below except try catch one work)

34 Answers

Try something like this:

if (typeof me.onChange !== "undefined") { 
    // safe to use the function
}

or better yet (as per UpTheCreek upvoted comment)

if (typeof me.onChange === "function") { 
    // safe to use the function
}

Modern JavaScript to the rescue!

me.onChange?.(str)

The Optional Chaining syntax (?.) solves this

In the example above, if a me.onChange property exists and is a function, it is called.

If no me.onChange property exists, nothing happens: the expression just returns undefined.

If a me.onChange property exists but is not a function, a TypeError will be thrown just like when you call any non-function as a function in JavaScript. Optional Chaining doesn't do any magic to make this go away.

For me the easiest way :

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}

Put double exclamation mark i.e !! before the function name that you want to check. If it exists, it will return true.

function abc(){
}
!!window.abc; // return true
!!window.abcd; // return false
function js_to_as( str ){
     if (me && me.onChange)
         me.onChange(str);
}

I'll go 1 step further to make sure the property is indeed a function

function js_to_as( str ){
     if (me && me.onChange && typeof me.onChange === 'function') {
         me.onChange(str);
     }
}
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

OR

function function_exists(func_name) {
  //  discuss at: http://phpjs.org/functions/function_exists/
  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Steve Clay
  // improved by: Legaev Andrey
  // improved by: Brett Zamir (http://brett-zamir.me)
  //   example 1: function_exists('isFinite');
  //   returns 1: true

  if (typeof func_name === 'string') {
    func_name = this.window[func_name];
  }
  return typeof func_name === 'function';
}

In a few words: catch the exception.

I am really surprised nobody answered or commented about Exception Catch on this post yet.

Detail: Here goes an example where I try to match a function which is prefixed by mask_ and suffixed by the form field "name". When JavaScript does not find the function, it should throw an ReferenceError which you can handle as you wish on the catch section.

function inputMask(input) {
  try {
    let maskedInput = eval("mask_"+input.name);

    if(typeof maskedInput === "undefined")
        return input.value;
    else
        return eval("mask_"+input.name)(input);

  } catch(e) {
    if (e instanceof ReferenceError) {
      return input.value;
    }
  }
}

With no conditions

me.onChange=function(){};

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

I would suspect that me is not getting correctly assigned onload.

Moving the get_ID call into the onclick event should take care of it.

Obviously you can further trap as previously mentioned:

function js_to_as( str) {
  var me = get_ID('jsExample');
  if (me && me.onChange) {
    me.onChange(str);
  }
}

I have also been looking for an elegant solution to this problem. After much reflection, I found this approach best.

const func = me.onChange || (str => {}); func(str);

I would suggest using:

function hasMethod(subject, methodName) {
  return subject != null && typeof subject[methodName] == "function";
}

The first check subject != null filters out nullish values (null and undefined) which don't have any properties. Without this check subject[methodName] could throw an error:

TypeError: (undefined|null) has no properties

Checking for only a truthy value isn't enough, since 0 and "" are both falsy but do have properties.

After validating that subject is not nullish you can safely access the property and check if it matches typeof subject[methodName] == "function".


Applying this to your code you can now do:

if (hasMethod(me, "onChange")) {
  me.onChange(str);
}

Try this one:

Window.function_exists=function(function_name,scope){
//Setting default scope of none is provided
If(typeof scope === 'undefined') scope=window;
//Checking if function name is defined
If (typeof function_name === 'undefined') throw new 
Error('You have to provide an valid function name!');
//The type container
var fn= (typeof scope[function_name]);
//Function type
If(fn === 'function') return true;
//Function object type
if(fn.indexOf('function')!== false) return true; 
return false;
}

Be aware that I've write this with my cellphone Might contain some uppercase issues and/or other corrections needed like for example functions name

If you want a function like PHP to check if the var is set:

Window.isset=function (variable_con){
If(typeof variable_con !== 'undefined') return true;
return false;
}

To illustrate the preceding answers, here a quick JSFiddle snippet :

function test () {
console.log()

}

console.log(typeof test) // >> "function"

// implicit test, in javascript if an entity exist it returns implcitly true unless the element value is false as :
// var test = false
if(test){ console.log(true)}
else{console.log(false)}

// test by the typeof method
if( typeof test === "function"){ console.log(true)}
else{console.log(false)}


// confirm that the test is effective : 
// - entity with false value
var test2 = false
if(test2){ console.log(true)}
else{console.log(false)}

// confirm that the test is effective :
// - typeof entity
if( typeof test ==="foo"){ console.log(true)}
else{console.log(false)}

/* Expected :
function
true 
true 
false
false
*/

// just pass your tested function name instead of myFunctionName
if ( $.isFunction($.fn.myFunctionName) ) {
    console.log( 'write your code here.' );
}

This will verify if the function exists, if so it will be executed

me.onChange && me.onChange(str);

Thus the error TypeError: me.onChange is not a function is prevent.

I prefer it using lodash library as below (looks much cleaner):

if (_.has(me, "onChange")) {
   // your desired code here
}

// or generic one like

if (_.has(this, "some property or function name")) {
   // your desired code here
}
function isFunction( o ) { return null !== o && "function" === typeof o && !!o.apply; }
Related