calling a function whose name is passed as an argument

A

Andrew Poulos

Say I have this

foo = function() {
// blah
};

bar = fuction(fnName) {
/* If fnName equalled "foo"
* How do I test that foo, as a function,
* exists and then, if it exists, call it?
*/

// I tried testing with this
if (typeof window[fnName] != 'undefined') {
/* but a variable of the same name would
* also be true wouldn't?
*/
}
};

Andrew Poulos
 
S

slebetman

Say I have this

foo = function() {
// blah

};

bar = fuction(fnName) {
/* If fnName equalled "foo"
* How do I test that foo, as a function,
* exists and then, if it exists, call it?
*/

Are you REALLY passing the function by name? Most people would pass it
by reference.
// I tried testing with this
if (typeof window[fnName] != 'undefined') {

Assuming you're passing it by reference (its unthinkable otherwise)
have you tried:

if (fn && fn instanceof Function) {
fn();
}
 
S

Stevo

slebetman said:
Say I have this

foo = function() {
// blah

};

bar = fuction(fnName) {
/* If fnName equalled "foo"
* How do I test that foo, as a function,
* exists and then, if it exists, call it?
*/

Are you REALLY passing the function by name? Most people would pass it
by reference.
// I tried testing with this
if (typeof window[fnName] != 'undefined') {

Assuming you're passing it by reference (its unthinkable otherwise)
have you tried:

if (fn && fn instanceof Function) {
fn();
}

Adapted your example for function name strings (because Andrew was very
clear about wanting to pass the function name as a string in his example):

if(window[fn] && window[fn] instanceof Function){
return window[fn]();
}

I've had to do this exact thing, but I'm not worried about the risk of
variables existing with the same name (due to some extremely unique
function names) so I just do this:

if(window[fn]) return window[fn]();
 
R

RobG

Are you REALLY passing the function by name? Most people would pass it
by reference.
   // I tried testing with this
   if (typeof window[fnName] != 'undefined') {
Assuming you're passing it by reference (its unthinkable otherwise)
have you tried:
  if (fn && fn instanceof Function) {
    fn();
  }

Adapted your example for function name strings (because Andrew was very
clear about wanting to pass the function name as a string in his example):

if(window[fn] && window[fn] instanceof Function){
   return window[fn]();
}

There is a long and detailed thread about this:

<URL:
http://groups.google.com.au/group/c...c?hl=en&lnk=gst&q=isfunction#5d96aa7cb290ec3c

A javscript function can be defined as an object that implements an
internal [[Call]] method, i.e. that it can be called. The difficulty
is that you can't directly test for that other than actually
attempting to call it. While it is required that native functions
return true for:

typeof functionName === 'function'


there is no such requirement for host objects that can be called. For
example:

alert(typeof document.getElementById);

shows "function" in Firefox and "object" in IE, similarly:

alert( document.getElementById instanceof Function);

returns true in Firefox and false in IE.

So testing with either instanceof or typeof is only suitable if the
object to be tested is known to be a native object.

I've had to do this exact thing, but I'm not worried about the risk of
variables existing with the same name (due to some extremely unique
function names) so I just do this:

if(window[fn]) return window[fn]();

or remove the function wrapper and use:

fn && fn();

Which is probably suitable in most cases provided adequate testing
(i.e. unit, system and acceptance) is performed and developers are
aware of the limitations.
 
D

dhtml

RobG said:

I was almost going to recommend the jQuery 'isFunction' function here,
as a joke. e.g. This problem has already been solved. See
jQuery.isFunction.
A javscript function can be defined as an object that implements an
internal [[Call]] method, i.e. that it can be called. The difficulty
is that you can't directly test for that other than actually
attempting to call it. While it is required that native functions
return true for:

typeof functionName === 'function'

Just because something is callable doesn't mean it is a function.

"is a Function" can be roughly translated to Function.prototype is on
the object's prototype chain.

To determine that, instanceof and isPrototypeOf could be used. Except
for frames, because a function in an IFRAME doesn't have the parent
window's Function.prototype in its prototype chain, so a cross-frame
test would fail.

An object that implements [[Call]] isn't necessarily a Function. That's
what David spent many long replies trying to explain to Thomas, who
seemed to not understand the intent of David's isFunction.

The purpose of knowing if something is a function, rather than is
callable, seems to be to know if you can call 'call' or 'apply' directly
on that object.

Fortunately, isFunction isn't necessary and typeof is really all you
need (see below).
there is no such requirement for host objects that can be called. For
example:

alert(typeof document.getElementById);

shows "function" in Firefox and "object" in IE, similarly:

alert( document.getElementById instanceof Function);

returns true in Firefox and false in IE.

So testing with either instanceof or typeof is only suitable if the
object to be tested is known to be a native object.

There is no way to determine if a Host object is callable, other than to
try and call it, though that may result in Error. It would have been
better if the implementations (MSIE) had followed the spirit of the
typeof operator for Host objects. For example, in IE, getElementById is
an object that implements [[Call]].

Function.prototype.call.call(document.getElementById, document, "x");

Works in IE. This could only be possible if either:

A) document.getElementById implements [[Call]].
B) JScript has a special implementation of Function.prototype.call to
handle Host object.

Either way, we can still use the callable check with the typeof operator:

if(typeof x == "function")
Function.prototype.call.call(x, context, "x");

Garrett
 
T

Thomas 'PointedEars' Lahn

dhtml said:
I was almost going to recommend the jQuery 'isFunction' function here,
as a joke. e.g. This problem has already been solved. See
jQuery.isFunction.

I thought you might.
A javscript function can be defined as an object that implements an
internal [[Call]] method, i.e. that it can be called. The difficulty
is that you can't directly test for that other than actually
attempting to call it. While it is required that native functions
return true for:

typeof functionName === 'function'

Just because something is callable doesn't mean it is a function.

And that was not what was said. However, the opposite is likely to be true.
"is a Function" can be roughly translated to Function.prototype is on
the object's prototype chain.

Very roughly. One could also say you are mistaken here.
To determine that, instanceof and isPrototypeOf could be used.

But that would be foolish, because (you are contradicting yourself in the
next paragraph):
An object that implements [[Call]] isn't necessarily a Function.

It is not necessary that it is a function as long as it can be called.
That's what David spent many long replies trying to explain to Thomas, who
seemed to not understand the intent of David's isFunction.

That is what you still do not get.
The purpose of knowing if something is a function, rather than is
callable, seems to be to know if you can call 'call' or 'apply' directly
on that object.

True, but one would also need to determine whether the object has such
methods. Which appears to be something of a chicken-and-the-egg problem.
Fortunately, isFunction isn't necessary and typeof is really all you
need (see below).

It is not, of course.
There is no way to determine if a Host object is callable, other than to
try and call it, though that may result in Error.

There you contradict yourself again.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
dhtml said:
RobG said:
A javscript function can be defined as an object that implements an
internal [[Call]] method, i.e. that it can be called. The difficulty
is that you can't directly test for that other than actually
attempting to call it. While it is required that native functions
return true for:

typeof functionName === 'function'
Just because something is callable doesn't mean it is a function.

And that was not what was said. However, the opposite is likely to be true.

s/opposite/reverse/


PointedEars
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>,
Adapted your example for function name strings (because Andrew was very
clear about wanting to pass the function name as a string in his
example):

if(window[fn] && window[fn] instanceof Function){
return window[fn]();
}

That code is not entirely satisfactory as an example. The programmer
has a clear expectation of calling a function. If the function *IS*
always considered callable by the IF, then the IF is not needed.
Otherwise, if the function is not considered callable, the programmer's
expectation is silently unfulfilled.

But the programmer's expectation is probably worthwhile; and its absence
may not always be perceived on test and may be deleterious in operation.

Therefore the IF, in the example, requires an ELSE. The example cannot
tell whether there should be a message to the user, an alternate piece
of code, or just nothing; but it can be written like

if (window[fn] && window[fn] instanceof Function) {
return window[fn]() } ; else { DealWithFailure() }

which reminds the programmer that at least some thought is needed.
Remember that examples should be aimed at the less able programmer; and
he may well be so keen on working on the "callable" case as to forget
the "non-callable" case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top