4

This is a follow up question to This Question.

I like (and understand) the solution there. However, in the code I am working in, another way to solve the same problem is used:

function exist(sFN) {
    if(self[sFN]) return true;
    return false;
}

It seems to work fine, although I don't understand how. Does it work? How? What are minuses of this approach? Should I switch to solution from the other question?

Community
  • 1
  • 1
buti-oxa
  • 11,261
  • 5
  • 35
  • 44

7 Answers7

7

Try this:

function exist(sFN) {
 return (typeof sFN == 'function');
}
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • Sorry, my link was too short, and you missed it. I was aware of the correct solution from the very beginning. I made the link more visible. – buti-oxa Sep 17 '08 at 23:10
  • Just for the sake, in Firefox <3 using typeof on a RegExp return "function" instead of "object" see: http://mykenta.blogspot.com/2006/10/typeof-and-typeof.html – kentaromiura Oct 23 '08 at 06:18
  • so does that mean we're screwed? – SeanDowney Mar 30 '09 at 20:09
  • @SeanDowney, that depends. If you just need to know if you can call something, there's no problem with treating a RegExp as a function, because it is callable. Of course, you could explicitly check for RegExp if the distinction matters either way. – Matthew Crumley May 13 '09 at 16:10
6

Your condition is checking the existence of the "sFN" property in the "self" object. Anything that isn't null, undefined, 0, and "" will evaluate to true.

As others have said, you can use typeof, or instanceof to see if it's actually a function.

Looking at your linked example, you should read up on the difference between ==/!= and ===/!== in javascript. Short answer: ("" == null) is true, ("" === null) is false.

Glenn
  • 200
  • 1
  • 2
  • 6
3

just use typeof.

typeof(foobar)  // -> undefined
typeof(alert)   // -> function

You can't, however, defined a function based on typeof, because you'd need to pass an identifier which might not exist. So if you define function isfun(sym) { return typeof(sym) }, and then tried calling isfun(inexistent), your code would throw.

The fun thing about typeof is that it's an operator, not a function. So you can use it to check a symbol that's not defined without throwing.


if you assume a function in the global scope (i.e., not within a closure), you can define a function to check it as follows:

function isfun(identifier) {
  return typeof(window[identifier]) == 'function';
}

Here you pass an string for the identifier, so:

isfun('alert');   // -> true
isfun('foobar');  // -> false

closure?

Here's an example of a function defined within a closure. Here, the printed value would be false, which is wrong.

(function closure() { 
  function enclosed() {}
  print(isfun('enclosed'))
})()
kch
  • 77,385
  • 46
  • 136
  • 148
1

FYI: There is (or was) a nice pitfall for typeof.

FF2 returns 'function' for typeof(/pattern/). FF3, IE7, and Chrome all return 'object' for the same code. (I can't verify other browsers.)

Assuming everyone that used FF2 has upgraded, you're in the clear. But, that's probably a far-fetched assumption.

Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
0

Object.prototype.toString.apply(value) === '[object Function]'

Shaun
  • 706
  • 6
  • 11
0

You can't really wrap this in a method, but it's so simple there is really no need.

function bob()
{}

if( typeof bob == "function" )
    alert( "bob exists" );

if( typeof dave != "function" )
    alert( "dave doesn't" );
Tim Booker
  • 2,801
  • 1
  • 25
  • 36
-1

I read somewhere (here and here) that functions are properties of the window object, so you can do the following:

if (window.my_func_name) {
    my_func_name('tester!');
}

or for popups:

if (window.opener.my_func_name) {
    my_func_name('tester!');
}

A complete solution then:

function function_exists(func_name) {
    var eval_string;
    if (window.opener) {
        eval_string = 'window.opener.' + func_name;
    } else {
        eval_string = 'window.' + func_name;
    }
    return eval(eval_string + ' ? true : false');
}
Jrgns
  • 24,699
  • 18
  • 71
  • 77