Passing an object while dynamically calling a function

S

sfeher

Hi All,

I need to call a function(loaded with appendChild) for which I have the
name as a string.

....
var fnName = 'fn1';
var call = fnName + '('+ param +' )';
eval(call);

It works fine as long as the param is a string but when I try to pass
an object it does not work as toString kicks in. Is there a better way
of doing this other than eval? How can I pass an object to fn1? I
thought about marshalling but I hope there's a better way inside the
language. Can someone help me understand this?

Regards,
Sebastian
 
S

sfeher

To clarify this - I do not expect eval to work on anything but string.
That said, my hope is that Javascript has a way of getting a reference
to a function "by name" so I can avoid the need of marshalling and
using eval.
 
R

RobG

To clarify this - I do not expect eval to work on anything but string.
That said, my hope is that Javascript has a way of getting a reference
to a function "by name" so I can avoid the need of marshalling and
using eval.

Please don' t top-post, now everyone has to scroll down to the bottom
to see what you are talking about, then come back to the top to see the
reply.

All functions declared in a global scope are properties of the global
object. JavaScript provides two methods for getting references to
object properties - dot notation and square bracket notation.

To reference a global function using square bracket notation:

function foo() {...}

window['foo']();


To use a varaible:

var bar = 'foo';
window[bar](); // calls foo();


You use dot notation where the string supplied is the name of the
property you want to access (e.g. window.foo() in the above) and use
use square bracket notation when you want the supplied parameter to be
evaluated - 'foo' evaluates to foo, as does bar.

One final note, the window object may not be available in every user
agent that runs your script, so you might want to use the global object
instead (they are synonymous in browsers):

// Declare in global scope:
var _global = this;


Now use _global wherever you would have used window.

How do you load a function using appendChild? Or do you load the
script element containing the function using appendChild?


call is a method of the Function object, so not really a good name for
a variable (personal preference). To do what you want here (without
eval):

var _global = this;
var fnName = 'fn1';
var call = _global[fnName];

call is now a reference to the (presumably) function object fn1, and
call() should execute it.

You never 'pass an object' - you always 'pass' a reference to an
object.

A fundamental principle of JavaScript is that where a variable is
assigned a primitive value, then:

var a = 5;
var b = a;

Both a and b now have a value of 5, it is effectively copied to b.
Modifying the value of a will not have any effect on the value of b.

When a variable is assigned a value that is a reference to an object,
then:

var objA = new Object();
var objB = objA;

The value of objA is a *reference* to the object, so the reference is
copied to the value of objB. objA and objB now reference the same
object. Therefore modifying (the object referenced by) objA will also
modify (the object referenced by) objB - it is the same object.

So wherever the value of a variable is assigned to some other variable
( var b = a) its value is always copied, just that sometimes it is a
primitive value and other times it is a reference to an object. You
may hear the saying 'primitives are passed by value, objects are passed
by reference' - don't believe it, for me it completely obfuscated what
is really happening.


I hope I did! :)

If not, please let me know.
 
S

sfeher

RobG said:
Please don' t top-post, now everyone has to scroll down to the bottom
to see what you are talking about, then come back to the top to see the
reply.

My apologies... one more thing to know :)
Not to blame it on Google Groups but probably they should discourage
this by not placing the cursor at the top of the textarea on replies ..
All functions declared in a global scope are properties of the global
object. JavaScript provides two methods for getting references to
object properties - dot notation and square bracket notation.

To reference a global function using square bracket notation:

function foo() {...}

window['foo']();


To use a varaible:

var bar = 'foo';
window[bar](); // calls foo();


You use dot notation where the string supplied is the name of the
property you want to access (e.g. window.foo() in the above) and use
use square bracket notation when you want the supplied parameter to be
evaluated - 'foo' evaluates to foo, as does bar.

One final note, the window object may not be available in every user
agent that runs your script, so you might want to use the global object
instead (they are synonymous in browsers):

// Declare in global scope:
var _global = this;


Now use _global wherever you would have used window.

How do you load a function using appendChild? Or do you load the
script element containing the function using appendChild?

Right, it's the script that contains the function that gets loaded.
call is a method of the Function object, so not really a good name for
a variable (personal preference). To do what you want here (without
eval):

var _global = this;
var fnName = 'fn1';
var call = _global[fnName];

call is now a reference to the (presumably) function object fn1, and
call() should execute it.

Excellent! Thanks Rob.
You never 'pass an object' - you always 'pass' a reference to an
object.

A fundamental principle of JavaScript is that where a variable is
assigned a primitive value, then:

var a = 5;
var b = a;

Both a and b now have a value of 5, it is effectively copied to b.
Modifying the value of a will not have any effect on the value of b.

When a variable is assigned a value that is a reference to an object,
then:

var objA = new Object();
var objB = objA;

The value of objA is a *reference* to the object, so the reference is
copied to the value of objB. objA and objB now reference the same
object. Therefore modifying (the object referenced by) objA will also
modify (the object referenced by) objB - it is the same object.

So wherever the value of a variable is assigned to some other variable
( var b = a) its value is always copied, just that sometimes it is a
primitive value and other times it is a reference to an object. You
may hear the saying 'primitives are passed by value, objects are passed
by reference' - don't believe it, for me it completely obfuscated what
is really happening.

My understanding is that it's pretty similar to Java where everything
gets passed "by value", which in the case of non-primitive values is
actually "the value of the reference".

It means you can change the value of the reference but not the
reference itself (similar to the C++ pass by pointer).

It's quite tricky when it comes to passing Javascript functions along,
I don't get that yet either..
I hope I did! :)

If not, please let me know.

You sure did :)

Thank you,
Sebastian
 
L

Lasse Reichstein Nielsen

Hi All,

I need to call a function(loaded with appendChild) for which I have the
name as a string.

...
var fnName = 'fn1';
var call = fnName + '('+ param +' )';
eval(call);

It works fine as long as the param is a string but when I try to pass
an object it does not work as toString kicks in.

I'm surprised that the string works. It should only work for values
that has string representations that are also literal expressions
of the value (number, boolean, null, undefined and probably also
functions).
Is there a better way of doing this other than eval?

If you have the name of the function, and that is the name
it is available as in the global scope, you can either do
global scope lookup or use eval. In either case, only do
it on the function name and do the call directly. No need
to create a string containing the call and the evaluate it.

I.e., either (e.g.):

function globalVar(name) {
return this[name];
}
globalVar(fnName)(param);

or

eval(fnName)(param);
How can I pass an object to fn1?

The same way you would always do it: call the function. Going through
a string representation of a call is a detour, not a shortcut :)

/L
 
D

Dr John Stockton

JRS: In article <[email protected]>,
dated Wed, 28 Jun 2006 08:03:18 remote, seen in
news:comp.lang.javascript, (e-mail address removed) posted :
My apologies... one more thing to know :)
Not to blame it on Google Groups but probably they should discourage
this by not placing the cursor at the top of the textarea on replies ..

The cursor should be put at the top, because it facilitates removing
those parts that need not be quoted; putting it at the bottom would
encourage untrimmed quoting.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top