Допустим, я получаю анонимную функцию, которая должна воздействовать на ее контекст, но она отличается от того, привязана ли она к "окну" или к неизвестному объекту.
Как получить ссылку на объект, из которого вызывается анонимная функция?
РЕДАКТИРОВАТЬ, некоторый код:
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);
Вы могли бы законно спросить, почему, черт возьми, вы хотели бы сделать что-то подобное. Ну, я сначала хотел распаковать аргументы, переданные в виде массива. Так же, как оператор Python "*
" делает:
>>> args = [1,2,3]
>>> def foo(a,b,c) :
print a,b,c
>>> foo(*args)
1 2 3
Я покопался в SO и нашел сообщение , в котором говорилось бы использовать "apply ()":
function bar(callback, args){
this[callback].apply(this, args);
}
Интересно, так как он будет использовать текущее «this», если в объекте, и «window», если нет.
Но я думаю, что есть проблема:
Если «bar ()» сам находится в объекте, то «this» будет ссылаться на контейнер «bar ()», поэтому он не будет работать.
Кстати, Я бы не хотел передавать область видимости в качестве параметра .
Конечно, я могу объединить аргументы и функцию в виде строки, затем использовать eval, но я бы хотел использовать это, только если я не могу найти что-то более чистое.
Конечно, если это просто невозможно (в конце концов, это может быть), тогда я сделаю:
function foo(func, args)
{
eval("func("+args.join(", ")+");");
}
РЕДАКТИРОВАТЬ 2: полный сценарий, как указано в комментариях.
Я использую qunit для выполнения модульных тестов в Javascript. Это круто, но мне не хватает способа проверить, не вызывает ли что-то исключение.
Самый простой тест выполняется следующим образом:
/**
* Asserts true.
* @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
*/
function ok(a, msg) {
_config.Test.push( [ !!a, msg ] );
}
Идея состоит в том, чтобы сделать что-то вроде:
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 ] );
}
};
Если бы я мог избавиться от eval, было бы здорово. И почему я не хочу использовать область в качестве параметра? Потому что вы можете захотеть зациклить контейнер, ссылающийся на 20 функций с разными областями действия, и протестировать их все в цикле, вместо того, чтобы писать вещи вручную.