FuncA to call FuncB, passing newParam1 AND allParamsPassedIntoFuncA

B

Bonzo

From within a function, I want to pass a/some parameters to another
function, AND all arguments, passed into this function.

e.g.

function firstFunction(){
//this function may have been passed, 0, 1, or n arguments...
...
//call another function...
var someCalculatedValue = 'someValue';
anotherFunction(someCalculatedValue, [[[all args passed into
firstFunction]]]);
}

I understand, that I can use....

anotherFunction.apply( this, firstFunction.arguments);

to "pass" along ALL the arguments to the second function, but I CAN'T
seem to figure out, how to ALSO, pass other arguments (preferably as
the first args)

Cheers,
Bonzo
 
M

Michael Winter

On 21/11/2005 16:36, Duncan Booth wrote:

[snip]
anotherFunction.apply( this,
[extra1, extra2].concat(firstFunction.arguments));

As I recall, the Array.prototype.concat method only adds numeric
properties one-by-one if the object is an Array. The arguments object is
not an array, so it will be appended as-is:

[extra1, extra2, arguments]

Both Firefox and IE display this behaviour, though surprisingly Opera
does not[1].

The more correct approach would be to use the Array.prototype.push or
unshift methods to add the extra arguments to the arguments object, then
pass that to the apply method (which can take either an array or an
arguments object):

/* Add arguments to front */
Array.prototype.unshift.call(arguments, extra1, extra2);

or:

/* Add arguments to rear */
Array.prototype.push.call(arguments, extra1, extra2);

then:

anotherFunction.apply(this, arguments);

Notice that the arguments object should not be qualified as a property
of a function object.

It should be pointed out that JScript versions prior to 5.5 don't
implement the apply or call methods, neither do they implement the
unshift or push methods. All four can be emulated though, if necessary.

I also wonder about this approach in general. It seems rather odd that a
function should want to pass through arguments in this manner. Perhaps
an alternative design could avoid the scenario entirely.

Mike


[1] On further examination, the arguments object is actually an
Array object in Opera.
 
B

Bonzo

Duncan & Michael,

Thanks for the input... I will definitely check this option out...

I understand your concern over the design Michael, it is a rather
strange one (my design that is)

It evolves from the desire to build elements via the DOM, then add
eventHandlers to them. (This has already been done, and works like
magic in all browsers except IE)

In Moz, and Opera, I can use:

someElement.setAttribute('onclick', 'funcB(event, ' + param1 + ', ' +
param2 + ');');

This will create the attribute, register the event, and all is well...
of course, IE will fail horribly... it will set the attribute, but not
register the event.

So, option2, was to call addEventListener/attachEvent, to add the event
handling... the only problem being, that I can't pass params (which,
argue as one might, I simply need for the "magic" I'm cultivating...
read: "seriously dynamically dynamic HTML")

So, I hacked** together something, that will wrap the "event
registration" call, to register the events in Moz, Opera, IE, etc.
A-N-D, allow me to pass parameters!...

**In the hack, I want to pass the event (default first argument in Moz,
Opera, etc.) to my handler, BUT, also (for simplicity), also pass it
along to IE (cause it is plain anoying to have to retrieve it inside
every single event handler on my page, if I can pass it instead)
***(there is actually more, but I'm trying to simplify here)

Long Story short, I have the event, and I have the parameters, and thus
I want to call the event handling function, with the event, and all
arguments passed to my "event handler wrapper"... on to my actual event
handler...

</end-scary-js-idea>

Alternatively, I've been told I might have some luck, iterating over
the arguments, and building up a "function string" that I can eval()
when complete... I'm not sure if this will solve my problem either, but
it seems the "hackiest" of the ideas I've seen thus far.

PS for anyone that is thinking it, no, I can't just stuff in
foo.innerHTML = ''; Although this will work in IE, it is not where I
want, nor care to go.

Cheers,
Bonzo
 
R

RobG

Bonzo said:
Duncan & Michael,

Thanks for the input... I will definitely check this option out...

I understand your concern over the design Michael, it is a rather
strange one (my design that is)

It evolves from the desire to build elements via the DOM, then add
eventHandlers to them. (This has already been done, and works like
magic in all browsers except IE)

In Moz, and Opera, I can use:

someElement.setAttribute('onclick', 'funcB(event, ' + param1 + ', ' +
param2 + ');');

This will create the attribute, register the event, and all is well...
of course, IE will fail horribly... it will set the attribute, but not
register the event.

Have you considered using:


var parm1 = 'Parameter 1';
var parm2 = 'Parameter 2';

someElement.onclick = function(event){
funcB(event, parm1, parm2);
}
// ...


function funcB(e, p1, p2){
var e = e || window.event;
alert(e.type + '\n' + p1 + '\n' + p2);
}


Be careful with closures - they may or may not be what you are after,
they can be avoided if not.
So, option2, was to call addEventListener/attachEvent, to add the event
handling... the only problem being, that I can't pass params (which,
argue as one might, I simply need for the "magic" I'm cultivating...
read: "seriously dynamically dynamic HTML")

addEventListener is handy if you want to add multiple events, or don't
want to stomp on those that might already be there, but the above is
simpler and may suit better.
So, I hacked** together something, that will wrap the "event
registration" call, to register the events in Moz, Opera, IE, etc.
A-N-D, allow me to pass parameters!...

If you post a small demo of what you are trying to do, life may be simpler.

**In the hack, I want to pass the event (default first argument in Moz,
Opera, etc.) to my handler, BUT, also (for simplicity), also pass it
along to IE (cause it is plain anoying to have to retrieve it inside
every single event handler on my page, if I can pass it instead)

You can't (AKAIK).

IE has a different event model, you have to get window.event from the
called function, so each such function has to have at least:

function funcB(e)
{
var e = e || window.event;
}

or some similar approach. The alternative is to call the function with
something like:

funcB(event, window.event);

But then funcB has to be something like:

function funcB(eMoz, eIE)
{
var e = eMoz || eIE;
}

and you're back where you started.


***(there is actually more, but I'm trying to simplify here)

Long Story short, I have the event, and I have the parameters, and thus
I want to call the event handling function, with the event, and all
arguments passed to my "event handler wrapper"... on to my actual event
handler...

Then do as suggested above. An event handler wrapper can be used to
prevent closures, but otherwise shouldn't be necessary.

</end-scary-js-idea>

Alternatively, I've been told I might have some luck, iterating over
the arguments, and building up a "function string" that I can eval()
when complete... I'm not sure if this will solve my problem either, but
it seems the "hackiest" of the ideas I've seen thus far.

Yech, it may not be *the* 'hackiest', but certainly getting there.

PS for anyone that is thinking it, no, I can't just stuff in
foo.innerHTML = ''; Although this will work in IE, it is not where I
want, nor care to go.

You are right not try it - it will likely fail some of the time in all
browsers for some elements and all of the time in others.
 
B

Bonzo

Rob,

yeah, unfortunately I have thought of that... the trick I have, is that
I don't know if I will be passing 0, 1, 2, or n params...

I'll hack it a bit more, I'm sure I can come up with something that
will work. ;-)

Thanks for all the input folks!

Cheers,
Bonzo
 
R

RobG

Bonzo said:
Rob,

yeah, unfortunately I have thought of that... the trick I have, is that
I don't know if I will be passing 0, 1, 2, or n params...

Please quote what you are replying to, trim the excess. I guess you are
referring to:

someElement.onclick = function(event){
funcB(event, parm1, parm2);
}
// ...

function funcB(e, p1, p2){
var e = e || window.event;
alert(e.type + '\n' + p1 + '\n' + p2);
}


In the above, both IE and Geko (W3C?) event models 'event' will be
passed from the onclick as the first parameter. For Geko, 'e' will be a
reference to the event, in IE it will be undefined, hence it is given a
value using window.event. More explicitly, you could use:

if (typeof e == 'undefined' && window.event) {
var e = window.event;
} else {
// Deal with an event model we don't understand
}


But the original is shorter. In both cases, if you don't know how many
arguments funcB will get, use the arguments collection to get the rest
of the arguments from arguments[1] onward:

function funcB(e)
{
var e = e || window.event;

var arg;
for (var i=1, num=arguments.length; i<num; ++i){
arg = arguments;

// Do something with each arg, if there are any;

}
}

[...]
 

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
474,434
Messages
2,571,688
Members
48,796
Latest member
Greg L.

Latest Threads

Top