How can I have one function call another function dynamically?

R

Randell D.

Folks,

I'm sure this can be done legally, and not thru tricks of the trade - I
hope someone can help.

I'm writing a 'tool' (a function) which can be used generically in any
of my projects. When it completes, it can call a success, or a failure
function. The names of these success, or failure functions will differ,
and I'd like to know how I can pass the name of a function to my tool,
and how my tool can call the function, using that name...

Roughly speaking I want to have something like

function my_engine(success_function_name, failure_function_name)
{
// Processing code here chews data

// Then...
if(myResult==true)
{ success_function_name(); }
else
{ failure_function_name(); }
}

Anybody got any ideas/suggestions? I'm sure there was a js method that
I could use but I can't find reference to it in my O'Reilly JavaScript
pocket reference...

All help, via the newsgroup (so all can learn) will be greatly appreciated,

Thanks,
Randell D.
 
R

Robert

Randell said:
and I'd like to know how I can pass the name of a function to my tool,
and how my tool can call the function, using that name...

function callFunction(name)
{
var f = new Function(name+"()");
f();
}

But maybe it would be more convenient to just pass the function itself
as a parameter...

Robert.
 
A

ASM

Randell said:
Folks,

I'm sure this can be done legally, and not thru tricks of the trade - I
hope someone can help.

I'm writing a 'tool' (a function) which can be used generically in any
of my projects. When it completes, it can call a success, or a failure
function. The names of these success, or failure functions will differ,
and I'd like to know how I can pass the name of a function to my tool,
and how my tool can call the function, using that name...

Roughly speaking I want to have something like

function my_engine(success_function_name, failure_function_name)
{
// Processing code here chews data

// Then...
if(myResult==true)
{ success_function_name(); }

try :
Function(success_function_name);
with calling
my_engine('success', 'failure');

or
{ success_function_name }
or ?
{ eval(success_function_name) }
and calling :
my_engine('success()', 'failure()');
 
V

VK

I'd like to know how I can pass the name of a function to my tool,
and how my tool can call the function, using that name...

It is very simple. Just pass *function references*, not function names.

<script type="text/javascript">
function f1(fun1,fun2) {
fun1();
fun2()
}

function f2() {
alert('f2')
}

function f3() {
alert('f3');
}

function init(){
f1(f2,f3);
}

window.onload = init;
</script>
 
V

VK

Are you saying it is not valid JavaScript?

*Roughly* that.

var functionRef = new Function(arg1, arg2, arg3, ..., argN);

where all args except the last one treated as function arguments, and
the last one as function body.
so:

var helloWorld = new Function("alert('Hello world!);");

equals to

function helloWorld() {
alert('Hello world!);
}


var alertType = new Function("obj","alert(typeof(obj));");

equals to

function alertType(obj) {
alert(typeof(obj));
}

As such Function will be evaluated on each call, it's performance is
lower than with standard function(). So it's suggested to use it only
if you really need to create run-time functions from the scratch.
 
R

Robert

VK said:
*Roughly* that.

As such Function will be evaluated on each call, it's performance is
lower than with standard function(). So it's suggested to use it only
if you really need to create run-time functions from the scratch.

Yes, that is exactly what he asked for.
name -> function call
It could not have been done using a literal function to my knowledge.

Anyway,
eval(name+"()")
is a better solution.
 
M

Michael Winter

On 15/07/2005 11:54, Robert wrote:

[snip]
It could not have been done using a literal function to my knowledge.

No, it couldn't.
Anyway,
eval(name+"()")
is a better solution.

No, it isn't. Passing a function object reference is much better, as
David describes, and it's what the OP should use.

Mike
 
Y

Yann-Erwan Perio

Robert wrote:

Hi,
eval(name+"()")
is a better solution.

Using "eval" as property accessing technique isn't really a good
practice, in the posted case the function is called from within a
function iself called directly, so something like
this[name]();
would be a better solution:)

Anyway passing the reference, as yourself and others have suggested, is
the best - the OP just wasn't probably aware that functions are
first-class objects in javascript...


Cheers,
Yep.
 
R

Robert

Yann-Erwan Perio said:
Using "eval" as property accessing technique isn't really a good
practice, in the posted case the function is called from within a
function iself called directly, so something like
this[name]();
would be a better solution:)

Ahh interesting. So many ways to achieve something in Javascript :)
 
R

Robert

Michael said:
No, it isn't. Passing a function object reference is much better, as
David describes, and it's what the OP should use.

Yes, but that was not what he asked for.
 
M

Matt Kruse

Randell said:
I'd like to know how I can pass the name of a
function to my tool, and how my tool can call the function, using that
name...

Wow, all these posts and no one answered your question :)

Passing a reference to a function is best, but not always possible or
practical.

Since functions are just properties of the window object, you can do:

function callfunc(name) {
if (typeof(window[name])=="function") {
window[name]();
}
}
 
M

Michael Winter

Michael said:
[...] Passing a function object reference is much better [...]

Yes, but that was not what he asked for.

He asked how to have one function call another. His current approach is
to pass the name of that function, but I don't see why that should be
set in stone, particularly if there's a better way.

Mike
 
R

Randy Webb

Robert said:
Yes, that is exactly what he asked for.
name -> function call
It could not have been done using a literal function to my knowledge.

Anyway,
eval(name+"()")
is a better solution.

NO.

window[name+'()']

is a better solution.
 
Y

Yann-Erwan Perio

Randy said:
window[name+'()']

is a better solution.

I'm now reluctant to submit window[]-based solutions, for at least two
reasons:
- window[] implies that the host is a browser; using "this" would work
on all browsers, provided the function is called as a member of the
global object,
- window[] implies that the conception relies on global functions, which
generally indicates a namespace pollution, therefore often a lazy
conception.

Anyway, in your example you have to put the parentheses outside of the
identifier, otherwise this won't work.

The following should help the OP into misunderstanding everything:)

---
window["foo()"]=foo;
function foo(){alert("Hello, World!")};
function test(name){
this[name+"()"]();
}

test("foo");
 
M

Matt Kruse

Yann-Erwan Perio said:
- window[] implies that the host is a browser; using "this" would work
on all browsers, provided the function is called as a member of the
global object,

Using 'this' is highly sensitive to the calling environment also. For most
situations, referencing window[name]() will work while this[name]() might
not.
- window[] implies that the conception relies on global functions,
which generally indicates a namespace pollution, therefore often a
lazy conception.

I disagree.

Most people developing javascript are not experts at the language by any
means. Most code does not make use of closures or inner functions, but
instead has a bunch of global functions.
 
Y

Yann-Erwan Perio

Matt Kruse wrote:

Hi,
- window[] implies that the host is a browser; using "this" would work
on all browsers, provided the function is called as a member of the
global object,
Using 'this' is highly sensitive to the calling environment also. For most
situations, referencing window[name]() will work while this[name]() might
not.

As you say, the "this" value depends on the way the function is called:
if called as a method, then the "this" value will be the reference of
the object of which it is the method, if called as a function then the
"this" value will be a reference to the global object.

So if you want a function generic enough to be called as a member of
different objects (global object, custom object), and only operate with
the global object for the "this" value, then indeed referencing "window"
directly would be a good option (while I'd prefer, personally, use a
construct with an inner function returning the global object).

However I feel that, when calling a function, the "this" value inside
should be already known and should not depend on how the function is
called (an external parameter of the function, lack of encapsulation).
- window[] implies that the conception relies on global functions,
which generally indicates a namespace pollution, therefore often a
lazy conception.
I disagree.

Most people developing javascript are not experts at the language by any
means. Most code does not make use of closures or inner functions, but
instead has a bunch of global functions.

Your argument, AIUI, is strange you know; you say you disagree that
global functions indicate a lazy conception, and then you justify the
point by precising that the guys using the "global functions" approaches
are not javascript experts.

What should I conclude from this? Should I trust so-called professionals
who can only use global functions, and don't even understand the
paradigm of the language they're using, to be skilled enough to provide
me with quality code?

Or would you rather defend that conceptions based on global functions
can be as good as conceptions using the javascript paradigm to its full?


Regards,
Yep.
 
D

Dr John Stockton

JRS: In article <0DIBe.150880$on1.84486@clgrps13>, dated Fri, 15 Jul
2005 06:22:52, seen in Randell D.
Roughly speaking I want to have something like

function my_engine(success_function_name, failure_function_name)
{
// Processing code here chews data

// Then...
if(myResult==true)
{ success_function_name(); }
else
{ failure_function_name(); }
}

You can do that; you're passing the function as a parameter.

But the test line should be if (myResult) as comparing with true is
unnecessary.

You could also do

function Mine(X, Y, AF) {
// calculate with X Y getting answer R and result code Z
AF[Z] // call the Zth function in array AF
return R }

and call it as RR = Mine(XX, YY, [F0,F1,F2,F3,F4,F5]) which has
three parameters the last being an array of functions. You probably
won't want to, but it is illustrative to see that you can.


Sometimes I use
function FuncName(Fn) { // Fn is a function; return its name
return Fn.toString().match(/( \w+)/)[0] }
though it's just occurred to me that the matching may be sub-optimal -
though speed is not important as I use it.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top