从数组/对象/集合中删除匿名 JavaScript 函数
Posted
技术标签:
【中文标题】从数组/对象/集合中删除匿名 JavaScript 函数【英文标题】:Remove anonymous JavaScript function from array/object/Set 【发布时间】:2017-03-23 00:04:54 【问题描述】:Node的emitter.removeListener如何在ES2015中实现?向数组添加回调很简单:
let callbacks = [];
function registerCallback(handler)
callbacks.push(handler);
);
那个特定的函数以后如何在没有 registerCallback 返回 some identifier for the function 的情况下被删除?换句话说,unregisterCallback(handler)
应该不需要任何其他参数,并且应该删除该处理程序。 unregisterCallback
将如何检查之前是否添加了匿名函数?
运行handler.toString()
(可能还有一个哈希函数)是为函数创建标识符的可靠解决方案吗?或者unregisterCallback
应该如何遍历callbacks
以删除该特定元素? (或者在 Set 中的对象或函数中找到适当的键。)
mySet.add(function foo() return 'a')
mySet.has(function foo() return 'a') // false
【问题讨论】:
【参考方案1】:通常的解决方案是将函数本身作为参数传递给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");
但是名称唯一性的责任在于用户代码领域,这可能好也可能不好,具体取决于您的应用程序。
【讨论】:
谢谢。使用函数本身作为键也适用于 Set。 有趣的是,setTimeout()
和 setInterval()
返回一个标识符,而不是 clearTimeout()
和 clearInterval()
采用相同的功能。
@DanDascalescu 是的,这很有趣。这可能是因为这些函数是在 javascript 的 "functions as first-class citizen" 本质在文化上显而易见之前设计的。 JavaScript 最初的设计速度非常快,许多最初的设计都可以追溯到在该领域很差的 Java。这也可能是实现泄漏的情况。
@DanDascalescu 有人指出,在setTimeout
和setInterval
中使用函数本身会使在多个计时器中使用相同的函数变得更加困难。【参考方案2】:
您可以选择design,其中事件发射器返回一个可更新内部状态的可调用对象:
const dispose = sleep.on('sheep', ::sleep.tick)
sleep.once('baanough', dispose)
【讨论】:
以上是关于从数组/对象/集合中删除匿名 JavaScript 函数的主要内容,如果未能解决你的问题,请参考以下文章
Mongodb,使用javascript从一组对象中删除一个对象