简体   繁体   English

如何获得Javascript匿名函数的“this”(范围)?

[英]How to get the “this” (scope) of a Javascript anonymous function?

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 : 就像Python“ * ”运算符一样:

>>> 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()" : 我在SO中挖了一个帖子告诉使用“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. 有意思,因为如果在一个对象中它将使用当前的“this”,如果没有则使用“window”。

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. 如果“bar()”本身在一个对象中,那么“this”将引用“bar()”容器,因此它不会出现问题。

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. 我当然可以将参数和函数连接成一个字符串然后使用eval,但我只想在我找不到更清洁的东西时使用它。

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. 编辑2:完整场景,如评论中所述。

I'm using qunit to perform unit tests in Javascript. 我正在使用qunit在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. 如果我能摆脱eval,那就太好了。 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. 因为您可能希望循环引用具有不同范围的20个函数的容器,并在循环中测试它们而不是手动编写内容。

e-satis, E-SATIS,

The only way to do is to use call or apply method to set correct 'context'. 唯一的方法是使用call或apply方法来设置正确的“上下文”。

To solve your problem, modify your bar function to accept callback function as well as the scope to apply to that callback function. 要解决您的问题,请修改条形函数以接受回调函数以及应用于该回调函数的范围。

function bar(callback, scope)
{
    callback.apply(scope);
}

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo, ObjectFromOtherLibIAmNotSupposedToknowAbout);

Alternatively, you can use a 'bind' method. 或者,您可以使用“绑定”方法。

Function.prototype.bind = function(context) {
  var fun = this;
  return function(){
    return fun.apply(context, arguments);
  };
};

Now, you can leave your bar function untouched and modify the calling code to look like, 现在,您可以保持条形函数不变,并修改调用代码,看起来像,

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo.bind(ObjectFromOtherLibIAmNotSupposedToknowAbout));

EDIT: 编辑:

As I noted in the comment, it's responsibility of the calling code to pass a correct callback function. 正如我在评论中指出的那样,调用代码负责传递正确的回调函数。 Your 'bar' function can not determine what scope to use, period. 您的“条形”功能无法确定使用的范围,句点。

Take this for an example, 以此为例,

var LibObject = { foo: function() { //use this inside method } };

var fooFunction = LibOjbect.foo;
bar(fooFunction);

How are you going to figure out what should be the scope? 你怎么弄清楚范围应该是什么? There is nothing for you to 'parse' now and there is no way you can modify your 'bar' function to make this work. 现在没有任何东西可以“解析”,你无法修改你的“条形”功能来完成这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM