2016-11-09 3 views
2

노드의 emitter.removeListener을 어떻게 ES2015에 구현할 수 있습니까? 배열에 콜백을 추가하는 것은 간단하다array/object/Set에서 익명 JavaScript 함수를 제거하십시오.

let callbacks = []; 
function registerCallback(handler) { 
    callbacks.push(handler); 
}); 

어떻게 특정 기능이 registerCallback가 some identifier for the function을 반환하지 않고, 나중에 제거 할 수 있습니까? 즉, unregisterCallback(handler)에는 다른 매개 변수가 필요하지 않으므로 해당 처리기를 제거해야합니다. unregisterCallback 익명의 기능이 이전에 추가되었는지 어떻게 확인합니까?

handler.toString() (잠재적으로 해시 함수가 해당됨) 함수에 대한 식별자를 만드는 신뢰할 수있는 솔루션이 실행되고 있습니까? 아니면 unregisterCallback을 통해 callbacks을 반복하여 특정 요소를 제거해야합니까? (또는 세트에서 객체 또는 함수에서 해당 키를 찾을 수 있습니다.)

mySet.add(function foo() { return 'a'}) 
mySet.has(function foo() { return 'a'}) // false 

답변

3

일반적인 솔루션은 unregisterCallback 함수 인수로 함수 자체를 전달하는 것입니다. 이것이 jQuery에서 예를 들어 이루어진 것입니다. 그것은가 함수를 정의 할 수없는,

물론
function unregisterCallback(handler) { 
    var index = callbacks.indexOf(handler); 
    if (~index) callbacks.splice(index, 1); 
} 

가이 기능을 유지해야 사용자 코드를 의미

는 그래서 unregisterCallback 기능은 콜백의 인덱스를 찾기 위해 indexOf를 사용하는 registerCallback으로 전화하십시오.

이 작동하지 않습니다

registerCallback(function foo() { return 'a'}); 
// later... 
unregisterCallback(function foo() { return 'a'}); // this is a different function 

이 작동 :

// pass either the function or its name 
function unregisterCallback(handler) { 
    var index = -1; 
    if (typeof handler==="string") { 
     for (var i=0; i<callbacks.length; i++) { 
     if (callbacks[i].name===handler) { 
      index = i; 
      break; 
     } 
     } 
    } else { 
     index = callbacks.indexOf(handler); 
    } 
    if (~index) callbacks.splice(index, 1); 
} 
registerCallback(function foo() { return 'a'}); 
unregisterCallback("foo"); 

그러나 이름의 책임 :

function foo(){ 
    return 'a' 
} 
registerCallback(foo); 
// later... 
unregisterCallback(foo); // it's the same function 

또한 이름으로 제거 할 수있는 기능을 제공 할 수 있습니다 unicity는 사용자 코드 영역에 있습니다. 응용 프로그램에 따라 OK 일 수도 있고 아닐 수도 있습니다.

+1

감사합니다. 함수 자체를 키로 사용하면 Sets에서도 작동합니다. –

+1

'setTimeout()'과'setInterval()'은 동일한 함수를 사용하는'clearTimeout()'과'clearInterval()'이 아닌 식별자를 반환한다는 점에 흥미 롭습니다. –

+0

@DanDascalescu 네, 흥미 롭습니다. 자바 스크립트의 기능이 "일류 시민으로서의 기능"(https://en.wikipedia.org/wiki/First-class_function) 성격이 문화적으로 분명하기 전에 이러한 기능이 설계 되었기 때문일 것입니다. 자바 스크립트는 초기에 매우 빠르게 설계되었으며 많은 초기 설계가 해당 영역에서 열악한 Java로 추적 될 수 있습니다. 구현 누설의 사례 일 수도 있습니다. –

0

당신은 이벤트 이미 터가 내부 상태 업데이트하는 호출 반환하는 design 갈 수

const dispose = sleep.on('sheep', ::sleep.tick) 
sleep.once('baanough', dispose)