我有以下形式的代码,用户可以在其中指定稍后将调用的回调:
var _deferred = [];
var deferred = function(callback) {
_deferred.push(callback);
}
var doDeferred = function() {
for(var i = 0, max = _deferred.length; i < max; i++) {
_deferred[i].call();
}
}
for(var i = 0; i < 5; i++) {
deferred(function() {
console.log("Some deferred stuff");
});
}
doDeferred();
我想要认识到为deferred()指定的回调是一个解析为相同原点的匿名函数,并且只允许它添加一次。 Aka位于底部for循环中,当i = 1时会抛出异常。
像:
var deferred = function(callback) {
if(_deferred.indexOf(callback) !== -1) {
throw "Already added!";
}
_deferred.push(callback);
}
我可以通过添加“密钥”来想到许多方法,但我想知道我是否可以使用Function.caller的内容来创建“源哈希”?
有没有解决方案,我已经没有看到了?我真的更愿意接受这种负担,而不是将其推迟给延期的来电者并让他们提供某种独特的身份。
编辑:
澄清任何混淆。
是每次对deferred的调用都是一个唯一的函数对象,有自己的闭包等。因此我的indexOf总是会失败。这不是一个混乱点。
问题是这些匿名函数是在同一个地方声明的,它们是相同的代码,我该如何判断呢?我想确定声明性相等,而不是实例相等。我以为我可以以某种方式创建一个基于延迟调用者的哈希...
结论:
谢谢大家,好像这里没有真正优雅的解决方案。 toString方法不是确定的(具有相同主体的不同函数将与字符串一样测试) - 并且只是丑陋。我要把负担放在打电话上。
答案 0 :(得分:1)
据我所知,如果你有两个具有相同实体的匿名函数,它们在“==”运算符方面就不相同,所以我认为你不能做indexOf()。< / p>
您可以检查新功能是否与阵列中已有的功能相同。要做到这一点,只需将函数转换为字符串并检查是否相等:
String((function(){/*something*/})) == String((function(){/*something*/}))
应该返回true;
答案 1 :(得分:1)
var deferred = function(callback) {
if(_deferred.some(function(c){return c.toString() === callback.toString()})) {
throw "Already added!";
}
_deferred.push(callback);
}
这将在第一次添加重复方法签名时抛出错误。
答案 2 :(得分:1)
问题是,在底部的循环中,它们是不同的功能,所以公平地说它们都应该包括在内(老实说,不能保证两个函数的值都赢了根据当前存在的变量而不同。我也不确定'仅限于独特的功能'是人们所期望的,所以它可能导致大量的“调试”
这不是ECMAScript所要求的,但Function.toString()
通常会返回其内部结构。所以你可能想要:
var ids = [] // separate ID takes up slightly more space, but lookup should
// be faster.
var deferred = function(callback) {
var cbs = callback.toString() // or String(callback)
if(ids.indexOf( cbs ) !== -1)
{
throw "Already added!";
}
ids.push( cbs )
_deferred.push(callback);
}
如果您愿意使用for ... in循环:
var _deferred = {}
var deferred = function(callback) {
var cbs = callback.toString() // or String(callback)
if( _deferred[ cbs] )
{
throw "Already added!";
}
_deferred[ cbs] = callback;
}
// caution, this executes in arbitrary order.
var doDeferred = function() {
for(var i in _deferred) {
_deferred[i].call();
}
}
答案 3 :(得分:1)
虽然我不会认为这很优雅,但你可以使用他们的toString()方法来比较匿名函数。
var deferred = function(callback) {
var str = callback.toString();
for var i = 0; i < _deferred.length; i++) {
if (_deferred[i].toString() == str) {
throw "Already added!";
}
}
_deferred.push(callback);
}