...

View Full Version : Resolved Better to pass a function or method as an argument?



Dan06
07-16-2009, 05:28 PM
I have a function, which currently takes a method as an argument. Is it good, inconsequential, or bad to use a method rather than a function as an argument?

Following, for simplicity's sake, is short generic example of both the function and method versions:


function example(string, test){
test(string);
}

example("Hello", function(text){document.write(text);})




function example2(string, obj){
obj.test(string);
}

example2("Hello", { test : function(text){ document.write(text); } })

jkd
07-16-2009, 05:48 PM
If the object exists solely to package the function in as a method (no real distinction between the two in javascript), then it is wasteful. Just pass the function directly.

rnd me
07-17-2009, 01:43 AM
If the object exists solely to package the function in as a method (no real distinction between the two in javascript), then it is wasteful.

methods have a different "this" than do functions, which get "window" or a called/applied-specific "this".

in the trivial example, it doesn't much matter.
methods share "this", so a more complicated version of {test} could use something like document.write(this.format(text)); , where format is another method on the same object.

like i said, not very useful for simple examples, but as complexity increases, methods provided the advantage of being iterable and contained in a single namespace, which can make them easier to find and use.

methods also provide two distinct function references: the method path/name, and an optional function name that can only be reached inside the method itself.
the path refers to the function object and the private name refers to an instance of that object, aka arguments.callee.

Dan06
07-17-2009, 08:37 PM
Thanks for the insight/feedback. The function at the source of my question is an AJAX function, to which I was passing a (callback) method. For the most part the callbacks were simple, so I was curious should I convert the AJAX function to use functions as arguments rather than methods. But, with the possibility of my callbacks becoming more complex, I chose to keep the AJAX function as is - i.e. accepting methods as arguments.

jkd
07-18-2009, 05:52 AM
methods have a different "this" than do functions, which get "window" or a called/applied-specific "this".

Still no distinction. Recall that the global object (in a browser context) is window. So it is only natural that unprefixed function calls default to window, since of course, that *is* the implied prefix.



in the trivial example, it doesn't much matter.
methods share "this", so a more complicated version of {test} could use something like document.write(this.format(text)); , where format is another method on the same object.


Dynamic dispatch. It's a wonderful thing.

Trinithis
07-19-2009, 05:40 AM
Not to sound nitpicky, but strictly speaking you can't pass methods around. In short, a method in Javascript is a function that only gains 'method-status' on application from an object.



var x = {
f: function () {
return this;
}
};

g = x.f; // g does not inherit x as this

// executed in Firefox
alert (g ()); // [object Window]
alert (x.f ()); // [object Object]
alert ((x.f) ()); // [object Object]... kind of surprised me


So what you are considering is whether or not to pass an object or a function (... yes, these are objects too) to your function.

The issue with passing an object is that you need to know the method name beforehand and settle on it. Not very malleable. In your example, you are stuck with using xxxx.test. Personally, I dislike that. An improvement perhaps is to pass the attribute name:


function example3 (string, obj, meth) {
obj [meth] (string);
}

var obj = { test : function (text) { document.write (text); } };
example3 ("Hello", obj, "test");


I don't like this either.

I do, however, love passing functions around. After all, Javascript does have first-class functions. Not only does this allow you to pass them around, but you can have nested functions. Fun! Just be careful about memory leaks that occur in crappy browsers (Internet Explorer :mad:) and DOM objects.

If you feel like an object is needed... well, this approach supports that too! Wrap the method call in a function!


Function.bundle = function (context, f, args) {
if (typeof f == "string" && context)
f = context [f];
if (arguments.length < 3)
args = [];
else if ( !(args instanceof Array))
args = Array.prototype.slice.call (arguments, 2);
return function () {
return f.apply (context, args);
};
};

function example (string, test) {
test (string);
}

var obj = { test : function (text) { document.write (text); } };
example ("Hello", Function.bundle (obj, "test"));



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum