2009-05-05 4 views
0

전 js 코드를 더 OOP 스타일로 옮깁니다. 여기에 코드가 있습니다.mousedown 이벤트를 프로토 타입에 추가 한 후에 mousemove 이벤트를 추가 할 수없는 이유는 무엇입니까?

function addEvent(obj, type, fn) { 
    if (obj.attachEvent) { 
    obj['e'+type+fn] = fn; 
    obj[type+fn] = function(){obj['e'+type+fn](window.event);} 
    obj.attachEvent('on'+type, obj[type+fn]); 
    } else 
    obj.addEventListener(type, fn, false); 
} 

function test() { 

} 

test.prototype = { 
    init: function() { 

     addEvent(document, 'mousedown', this.displaydown); 

    }, 

    displaydown : function(e){ 
     document.getElementById('mydiv').innerHTML = "down"; 
     addEvent(document, 'mousemove', this.displaymove); 
    }, 

    displaymove : function(e){ 
     document.getElementById('mydiv').innerHTML = "move"; 
    } 
} 

var test0 = new test(); 

test0.init() 

나는

addEvent(document, 'mousemove', this.displaymove); 

와 mousedown 후에서 mousemove 이벤트를 추가 할 수 없습니다하지만

addEvent(document, 'mousemove', function(e){ 
    document.getElementById('mydiv').innerHTML = "move"; 
}); 

같이 인라인 스타일을 작성하는 경우는 OK입니다. 그것은 2 개의 코드가 똑같이하는 것처럼 보입니다. 차이점은 무엇입니까? 감사!


편집,

2 박에 대한 투쟁 후 드디어 문제를 해결했다. 귀하의 enlighting 주셔서 감사합니다 johnvey.

에로는 에이 키워드로 발생합니다. 객체의 경우 객체 자체가 아니라 윈도우를 참조합니다. 해결책은 처음에 전역 매개 변수 (me = this)을 정의한 것입니다. 이제 괜찮아.

답변

2

이것은 "this"키가 클로저 안에서 어떻게 범위 지워지는 것과 관련하여 고전적인 자바 스크립트 걸림돌입니다. 설명하기 :

redPrinter = function() { 
    this.X = 'red'; 
    return function() { 
     return this.X; 
    } 
} 

main = function() { 
    this.X = 'blue'; 
    var myRedPrinter = new redPrinter(); 
    alert("Red printer returned: " + myRedPrinter()); 
} 

main(); 

이 코드가 인쇄됩니다

Red printer returned: blue 

을의 범위가 '이'가 라인 때문에 :

return this.X 

실제로 주() 객체에 연결되어 발동 당시. 함수 클로저 내에서 '이'키워드를 사용하여

1) 피하십시오 :

는 일반적으로이 문제를 해결하는 두 가지 방법이 있습니다. 이런 방식으로 코드를 수정하려면 모든 이벤트 바인딩을 계단식으로 묶는 대신 한 곳에서 수집하여 'displaydown()'및 'displaymove()'에서 'this'참조를 제거하십시오.

또는

2) 정의 시간에 범위를 바인딩하는 기능을 사용하십시오. 여기

// declare the global bind() method for all functions 
Function.prototype.bind = function(obj) { 
    var method = this, 
    temp = function() { 
     return method.apply(obj, arguments); 
    }; 
    return temp; 
} 

test.prototype = { 
    init: function() { 
     addEvent(document, 'mousedown', this.displaydown); 
    }, 

    displaydown : function(e){ 
     document.getElementById('mydiv').innerHTML = "down"; 

     // note that we bind the method object here 
     addEvent(document, 'mousemove', this.displaymove.bind(this)); 
    }, 

    displaymove : function(e){ 
     document.getElementById('mydiv').innerHTML = "move"; 
    } 
} 

중요한 변화는 다음과 같습니다 : 나는 설명하기 위해 프로토 타입 라이브러리에서 바인드() 메소드를 해제 한 당신이 displaymove()를 호출 할 때 "기본적으로 말한다

this.displaymove.bind(this) 

, 다시 'this'키워드를 현재 Event 객체가 아닌 원래 스코프 컨텍스트로 범위 지정하십시오.

+0

안녕하세요, johnvey 감사합니다! 제 2 방법으로해야한다고 생각하지만 바인딩 할 수 없습니다().이 단계에서 오류가 발생합니다. 나는 IE.6을 사용하고있다. 이것이 이유입니까? – unigogo

+0

IE6이 문제가 아니어야합니다. 당신이 겪고있는 오류는 무엇입니까? 큰 질문으로, 당신이하려는 것은 무엇입니까? 다른 이벤트 핸들러 내부에서 addEvent()를 호출하면 좋지 않습니다. 동일한 핸들러를 반복해서 붙이게 될 것이기 때문입니다. – johnvey

+0

johnvey, 마침내 코드에서 오류를 발견했습니다. addEvent (document, 'mousedown', this.displaydown); 또한 바인딩되어야합니다. 또는 mousedown의 범위에있는 창입니다. 난 그냥 쉽게 로딩을위한 슬라이더에서 일했습니다. http://www.pagecolumn.com/webparts/sliders.htm – unigogo

관련 문제