Let's say I get an anonymous function an need to act on its context, but it's different whether it's binded to "window" or an unknown object.
How do I get a reference to the object an anonymous function is called from?
EDIT, some code :
var ObjectFromOtherLibIAmNotSupposedToknowAbout = {
foo : function() {
// do something on "this"
}
}
var function bar(callback) {
// here I want to get a reference to
// ObjectFromOtherLibIAmNotSupposedToknowAbout
// if ObjectFromOtherLibIAmNotSupposedToknowAbout.foo is passed
// as callback
}
bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo);
You might legitimately ask, why does the heck would you like to do something like that. Well, I first wanted to unpack arguments passed as an array. Just like the Python "*
" operator does :
>>> args = [1,2,3]
>>> def foo(a,b,c) :
print a,b,c
>>> foo(*args)
1 2 3
I dug in SO and found a post telling to use "apply()" :
function bar(callback, args){
this[callback].apply(this, args);
}
Interesting since it's going to use the current "this" if in an object, and "window" if not.
But I think there is a problem :
if "bar()" is itself in an object, then "this" will refer to the "bar()" container, therefor it won't worK.
BTW, I would like not to pass the scope as a parameter.
I can of course concatenate the arguments and the function as a string then use eval, but I'd like to use this only if I can't find something cleaner.
Of course, if it's just impossible (after all, it could be), then I'll do :
function foo(func, args)
{
eval("func("+args.join(", ")+");");
}
EDIT 2 : full scenario, as asked in comments.
I'm using qunit to perform unit tests in Javascript. It's cool, but I miss a way to check if something raises an Exception.
The most basic test is done that way :
/**
* Asserts true.
* @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
*/
function ok(a, msg) {
_config.Test.push( [ !!a, msg ] );
}
The idea is to make something like :
jqUnit.prototype.error = function(func, args, msg)
{
try
{
eval("func("+args.join(", ")+");");
config.Test.push( [ false, msg + " expected : this call should have raised an Exception" ] );
} catch(ex)
{
_config.Test.push( [ true, msg ] );
}
};
If I could get rid of eval, it would be great. And why don't I want to use the scope as a parameter ? Because you may want to loop on a container referencing 20 functions with different scopes and test them all in the loop instead of writting the stuff by hand.