2016-11-09 125 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)