簡體   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