繁体   English   中英

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

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

假设我得到一个匿名函数需要对其上下文进行操作,但它是否与“窗口”或未知对象绑定是不同的。

如何从对象中引用匿名函数?

编辑,一些代码:

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个函数的容器,并在循环中测试它们而不是手动编写内容。

E-SATIS,

唯一的方法是使用call或apply方法来设置正确的“上下文”。

要解决您的问题,请修改条形函数以接受回调函数以及应用于该回调函数的范围。

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

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo, ObjectFromOtherLibIAmNotSupposedToknowAbout);

或者,您可以使用“绑定”方法。

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

现在,您可以保持条形函数不变,并修改调用代码,看起来像,

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

编辑:

正如我在评论中指出的那样,调用代码负责传递正确的回调函数。 您的“条形”功能无法确定使用的范围,句点。

以此为例,

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

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

你怎么弄清楚范围应该是什么? 现在没有任何东西可以“解析”,你无法修改你的“条形”功能来完成这项工作。

暂无
暂无

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

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