2009-10-11 4 views
8

익명 함수가 컨텍스트에 따라 행동 할 필요가 있다고 가정 해 봅시다. 그러나 "창이"또는 알 수없는 개체에 바인드되는지 여부는 다릅니다.Javascript 익명 함수의 "this"(범위)를 얻는 방법은 무엇입니까?

익명 함수가 호출 된 개체에 대한 참조를 얻으려면 어떻게해야합니까?

편집, 일부 코드 : 당신은 합법적으로 요청할 수 있습니다

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); 

, 왜 도대체 당신이 그런 일을하고 싶습니다 않습니다. 자, 먼저 배열로 전달 된 인자를 풀고 싶었습니다. 그냥 파이썬처럼 "*"연산자 수행합니다

>>> args = [1,2,3] 
>>> def foo(a,b,c) : 
     print a,b,c 
>>> foo(*args) 
1 2 3 

내가 SO 파고와 ") (적용"을 사용하라는 post을 발견 : "현재를 사용하는 것 때문에

function bar(callback, args){ 
    this[callback].apply(this, args); 
} 

흥미 롭 이 "는 객체에있는 경우"창 ", 그렇지 않은 경우에는"창 "입니다.

는하지만 문제가 있다고 생각 :

"바()"객체 자체 인 경우, 다음 "이"가 "바()"컨테이너를 참조 것, 그 때문에이 작동하지 않습니다.

BTW, 매개 변수으로 범위를 전달하지 않으려합니다.

물론 인수와 함수를 문자열로 연결 한 다음 eval을 사용할 수 있지만 클리너를 찾을 수없는 경우에만 사용하고 싶습니다. 그것은 (결국, 그것은 수) 단지 불가능하면 물론

, 그럼 내가 할 수있는 것들 :

function foo(func, args) 
{ 
    eval("func("+args.join(", ")+");"); 
} 

편집 2 : 의견 요청으로 전체 시나리오를.

저는 qunit을 사용하여 자바 스크립트에서 단위 테스트를 수행하고 있습니다. 멋지다. 그러나 뭔가 예외가 발생했는지 확인하는 방법을 놓친다.

가장 기본적인 테스트는 그런 식으로 이루어집니다 :

내가 평가를 제거 할 수 있다면
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 ]); 
    } 
}; 

, 그것은 좋은 것 :

/** 
* Asserts true. 
* @example ok($("a").size() > 5, "There must be at least 5 anchors"); 
*/ 
function ok(a, msg) { 
    _config.Test.push([ !!a, msg ]); 
} 

아이디어는 같은 것을 만드는 것입니다. 왜 내가 범위를 매개 변수로 사용하고 싶지 않은가? 왜냐하면 서로 다른 범위의 20 개 함수를 참조하는 컨테이너에서 반복 작업을 수행하고 손으로 물건을 쓰는 대신 루프에서 모두 테스트하기를 원할 수 있기 때문입니다.

+2

몇 가지 코드 예를 제공해 주시겠습니까? 나는 당신이 정말로 원하는 것을 이해하는 데 약간의 어려움이 있습니다. –

+0

예, 당신이 무엇을 찾고 있는지 잘 모르겠습니다. 몇 가지 코드 샘플을 입력하십시오. – SolutionYogi

+0

네 말이 맞아. –

답변

6

전자 satis,

할 수있는 유일한 방법은 전화를 사용하거나 올바른 '컨텍스트'를 설정하는 방법을 적용하는 것입니다.

문제를 해결하려면 해당 콜백 함수에 적용 할 범위와 콜백 함수를 허용하도록 막대 기능을 수정하십시오.

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); 

당신은 어떻게 범위해야 알아낼거야, 예제이 걸릴? 이제는 '구문 분석'할 수있는 것이 없으며 '바'기능을 수정하여이 작업을 수행 할 수있는 방법은 없습니다.

+1

안녕하세요, 감사합니다.하지만 단위 테스트 프레임 워크를 약간 확장 해킹했기 때문에 테스트 된 기능의 범위가 아직 없습니다. –

+0

바 메서드 호출을 작성 하시겠습니까? JS에서는 함수가 객체에 첨부되지 않으며 JS engine은 call/apply를 사용하여 명시 적으로 지정하지 않으면 JS 엔진이 사용할 컨텍스트를 결정합니다. – SolutionYogi

+0

나는 어쨌든 1000 가지 테스트를 (qunit 구문), 특정 서명으로 쓰도록 요청할 수는 없으며 편의를 위해 코딩 한 약간의 해킹을 제외하고는 예외로 만들 수 있습니다. 그럴 가치가없는 API 일관성을 깨뜨릴 수 있습니다. 큰 문제는 아니지만이 질문은 삶과 죽음의 문제가 아닙니다 :-) –