2010-06-09 3 views
1

콜백 함수가 작동하는 데 문제가 있습니다.Javascript 콜백의 범위 지정 문제

SomeObject.prototype.refreshData = function() 
{ 
    var read_obj = new SomeAjaxCall("read_some_data", { }, this.readSuccess, this.readFail); 
} 

SomeObject.prototype.readSuccess = function(response) 
{ 
    this.data = response; 
    this.someList = []; 
    for (var i = 0; i < this.data.length; i++) 
    { 
     var systemData = this.data[i]; 
     var system = new SomeSystem(systemData); 
     this.someList.push(system); 
    } 
    this.refreshList(); 
} 

은 기본적으로 SomeAjaxCall는 데이터에 대한 아약스 요청을하고있다 : 여기 내 코드입니다. 작동한다면 우리는 콜백 'this.readSuccess'를 사용하고 실패하면 'this.readFail'을 사용합니다.

SomeObject.readSuccess의 'this'는 전역 콜백 (윈도우 개체라고도 함)입니다. 콜백이 함수가 아니라 멤버 메서드로 호출되기 때문입니다. 내 이해는 내가 주변에 '이것'을 유지하기 위해 폐쇄를 사용해야하지만, 나는 이것을 작동시킬 수 없었다.

누군가 내가 할 수있는 것을 보여줄 수 있다면 나는 그것을 크게 고맙게 여길 것입니다. 나는 아직도 폐쇄가 작동하는 방법과 특히이 상황에서 어떻게 작동 할 것인가에 관해 머리 글자를 쓰고있다.

감사합니다.

SomeObject.prototype.refreshData = function() 
{ 
    var obj = this; 
    var read_obj = new SomeAjaxCall("read_some_data", { }, 
    function() { obj.readSuccess(); }, function() { obj.readFail(); }); 
} 

일부 자바 스크립트 프레임 워크 유틸리티에 "바인딩"개체에 대한 기능, 단순히 수단을 제공 할 수

답변

2

그럼 가장 간단한 것은 또 다른 함수에서 "this.readSuccess"을 래핑하는 것입니다 그 작은 기능 중 하나를 만듭니다. 변수 "obj"는 작은 함수에 의해 "기억"됩니다. 따라서 핸들러가 호출 될 때 "this"참조는 "refreshData"를 호출하는 데 사용 된 객체에 대한 참조가됩니다.

+0

, 여기서 일어나는 것은'obj'가 'function() {obj.readSuccess(); }'평가됩니다. Prototype이나 jQuery와 같은 라이브러리를 사용하지 않는 한 다른 방법은 없습니다. 이것들은 투명하게 클로저 생성을 할'.bind()'함수를 가지고있다. – MvanGeest

+0

nit-pick을 사용하지는 않지만 StackOverflow를 사용하기 위해서는 jQuery 버전을 "bind"가 아닌 "proxy"라고 부릅니다. – Pointy

+0

완벽한 의미가 있습니다. jQuery 프록시 함수가 작동합니다. 그러나 완벽을 기하기 위해 jQuery를 사용하지 않으면 어떻게 처리 할 것인지 혼란 스럽습니다. 필자의 예제에서 readSuccess는 나중에 채워지는 respnse라는 하나의 인수를가집니다. 그래서 그것은 function() {obj.readSuccess (wah ??); } 와우 이후 ?? 나중에 전달 될 예정입니다. 시도해 보았습니다. function() {obj.readSuccess; } 행운을 빌어 요. 이견있는 사람? – nazbot

0

다음 사이트에서는 문제가 "클래스"건물에서 사용되는 것보다 많을 수도 있음을 나타냅니다. "프로토 타입 속성을 사용하여 다시 작성"을 읽으면 "클래스"구조의 특정 메서드가 인스턴스 기반이 아닌 전역 메서드를 유지하게됩니다. 아마도 또 다른 창조 방법인가? 여기

http://devedge-temp.mozilla.org/viewsource/2001/oop-javascript/

2

귀하의 문제는 정확히 폐쇄 또는 범위 지정 문제가되지 않습니다. 문제는 변수에 this.readSuccess을 할당 할 때 본래 속한 객체의 개념없이 함수 자체를 할당한다는 것입니다. 같은 방법으로

, 당신은 정기적으로, "-자치"기능을 가지고 객체의 방법으로 사용할 수 있습니다 :

function hello() { 
    alert("Hello "+this.planet); 
} 
var planet = "Earth"; 
hello(); // -> 'Hello Earth' 

var Venus = { 
    planet: "Venus" 
}; 
hello.apply(Venus); // -> 'Hello Venus' 
Venus.hello = hello; 
Venus.hello(); // -> 'Hello Venus' 

그리고 당신의 문제는이 예에서 복제 될 수

var helloVenus = Venus.hello; 
helloVenus(); // -> 'Hello Earth' 

문제는 this.readSuccess를 일부 변수 에 할당하고이의 메소드로 호출해야합니다. Pointy가 시연 한 클로저로 수행 할 수 있습니다. "SomeAjaxCall"이 실제로 무엇인지 모르기 때문에 this의 값이 실제로 손실되는지 여부와 실제로 var obj = this이 필요한지를 아는 것은 어렵습니다.기회는 그렇지 않은 것을, 그래서 당신은 이러한 종류의 코드와 잘 될 수 있습니다 : 귀하의 경우

var helloVenus = function() { Venus.hello() } 
helloVenus(); // -> 'Hello Venus' 

, 즉 것

SomeObject.prototype.refreshData = function() 
{ 
    var read_obj = new SomeAjaxCall(
    "read_some_data", 
    { }, 
    function() { this.readSuccess.apply(this, arguments) }, 
    function() { this.readFail.apply(this, arguments) } 
); 
} 
: ( 편집 : 핸들러에 전달되는 인수를 추가)

앞에서 설명한 것처럼 몇 가지 js 프레임 워크는 이러한 종류의 문제를 단순화하기 위해 bind 함수를 제공합니다. 하지만 당신은 그냥이를위한 완벽한 프레임 워크를 필요가 없습니다 여기에 일반 자바 스크립트 작동 완벽하게 정상적으로 Function#bind 방법 : Function#bind의 도움으로

Function.prototype.bind = function(obj) { 
    var __method = this; 
    var args = []; 
    for(var i=1; i<arguments.length; i++) 
     args.push(arguments[i]); 
    return function() { 
     var args2 = []; 
     for(var i=0; i<arguments.length; i++) 
      args2.push(arguments[i]); 
     return __method.apply(obj, args.concat(args2)); 
    }; 
} 

, 당신은 쓸 수 있습니다 : 사실

SomeObject.prototype.refreshData = function() 
{ 
    var read_obj = new SomeAjaxCall(
    "read_some_data", 
    { }, 
    this.readSuccess.bind(this), 
    this.readFail.bind(this) 
); 
} 
+0

좋은 답변입니다. 정보를 가져 주셔서 감사합니다. – nazbot

+0

이고 bind는 ECMAScript 5의 일부입니다 : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind – w00t