2016-11-09 72 views
2
刪除匿名JavaScript函數

如何才能在ES2015中實現Node的emitter.removeListener?添加一個回調到一個數組很簡單:從array/object /設置

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所做的。

所以unregisterCallback函數只是擁有使用indexOf找到回調的指數:

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

當然,這意味着用戶代碼必須保持功能,它不能在被定義的函數致電registerCallback

這不起作用:

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

這工作:

function foo(){ 
    return 'a' 
} 
registerCallback(foo); 
// later... 
unregisterCallback(foo); // it's the same 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"); 

但名責任unicity然後在用戶代碼領域,這可能是好的,或不是,取決於您的應用程序。

+1

感謝。將函數本身用作密鑰也適用於Set。 –

+1

有趣的是,'setTimeout()'和'setInterval()'返回一個標識符,而不是'clearTimeout()'和'clearInterval()'具有相同的功能。 –

+0

@DanDascalescu是的,這很有趣。這可能是由於這些功能是在[作爲一等公民的功能]之前設計的(https://en.wikipedia.org/wiki/First-class_function),因此JavaScript的性質在文化上顯而易見。 JavaScript最初設計得非常快,許多最初的設計都可以追溯到那個領域內糟糕的Java。這也可能是實施泄漏的情況。 –

0

你可以去design凡在活動發射返回Callable將更新內部狀態:

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